toss-devel-svn Mailing List for Toss (Page 20)
Status: Beta
Brought to you by:
lukaszkaiser
You can subscribe to this list here.
2010 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(25) |
Dec
(62) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2011 |
Jan
(26) |
Feb
(38) |
Mar
(67) |
Apr
(22) |
May
(41) |
Jun
(30) |
Jul
(24) |
Aug
(32) |
Sep
(29) |
Oct
(34) |
Nov
(18) |
Dec
(2) |
2012 |
Jan
(19) |
Feb
(25) |
Mar
(16) |
Apr
(2) |
May
(18) |
Jun
(21) |
Jul
(11) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <luk...@us...> - 2010-12-30 22:58:07
|
Revision: 1273 http://toss.svn.sourceforge.net/toss/?rev=1273&view=rev Author: lukaszkaiser Date: 2010-12-30 22:58:00 +0000 (Thu, 30 Dec 2010) Log Message: ----------- Non-standard checkers (will be corrected). Modified Paths: -------------- trunk/Toss/WebClient/DefaultStyle.js trunk/Toss/WebClient/Login.js trunk/Toss/WebClient/MakeDB.py trunk/Toss/WebClient/Style.css trunk/Toss/WebClient/index.html Added Paths: ----------- trunk/Toss/examples/Checkers.toss trunk/Toss/examples/Checkers.tossstyle Modified: trunk/Toss/WebClient/DefaultStyle.js =================================================================== --- trunk/Toss/WebClient/DefaultStyle.js 2010-12-22 09:50:51 UTC (rev 1272) +++ trunk/Toss/WebClient/DefaultStyle.js 2010-12-30 22:58:00 UTC (rev 1273) @@ -227,14 +227,16 @@ var f = svg_from_string (pos[0], pos[1], 20, 20, '<g class="chessB" ' + is + hs + '>' + DEFrook + '</g>'); document.getElementById("svg").appendChild(f); - } else if (rel_name == "wQ") { // Chess Figure: white queen - var f = svg_from_string (pos[0], pos[1], 20, 20, - '<g class="chessW" ' + is + hs + '>' + DEFqueen + '</g>'); + } else if (rel_name == "wQ" || rel_name == "Wq") { + // Chess Figure: white queen or Checkers: white queen + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessW" ' + is + hs + '>' + DEFqueen + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "bQ" || rel_name == "Bq") { + // Chess Figure: black queen or Checkers: black queen + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessB" ' + is + hs + '>' + DEFqueen + '</g>'); document.getElementById("svg").appendChild(f); - } else if (rel_name == "bQ") { // Chess Figure: black queen - var f = svg_from_string (pos[0], pos[1], 20, 20, - '<g class="chessB" ' + is + hs + '>' + DEFqueen + '</g>'); - document.getElementById("svg").appendChild(f); } else if (rel_name == "wK") { // Chess Figure: white king var f = svg_from_string (pos[0], pos[1], 20, 20, '<g class="chessW" ' + is + hs + '>' + DEFking + '</g>'); Modified: trunk/Toss/WebClient/Login.js =================================================================== --- trunk/Toss/WebClient/Login.js 2010-12-22 09:50:51 UTC (rev 1272) +++ trunk/Toss/WebClient/Login.js 2010-12-30 22:58:00 UTC (rev 1273) @@ -23,10 +23,11 @@ document.getElementById("welcome").style.display = "none"; document.getElementById("plays").style.display = "block"; list_plays_string ("Breakthrough", udata[2]); - list_plays_string ("Chess", udata[3]); - list_plays_string ("Entanglement", udata[4]); - list_plays_string ("Gomoku", udata[5]); - list_plays_string ("Tic-Tac-Toe", udata[6]); + list_plays_string ("Checkers", udata[3]); + list_plays_string ("Chess", udata[4]); + list_plays_string ("Entanglement", udata[5]); + list_plays_string ("Gomoku", udata[6]); + list_plays_string ("Tic-Tac-Toe", udata[7]); get_opponents (); } Modified: trunk/Toss/WebClient/MakeDB.py =================================================================== --- trunk/Toss/WebClient/MakeDB.py 2010-12-22 09:50:51 UTC (rev 1272) +++ trunk/Toss/WebClient/MakeDB.py 2010-12-30 22:58:00 UTC (rev 1273) @@ -8,7 +8,8 @@ SERVER_FILE = "/var/www/WebClient/TossServer" GAMES_PATH = "../examples" -GAMES = ["Breakthrough", "Chess", "Entanglement", "Gomoku", "Tic-Tac-Toe"] +GAMES = ["Breakthrough", "Checkers", "Chess", "Entanglement", + "Gomoku", "Tic-Tac-Toe"] TUID = "toss_id_05174_" Modified: trunk/Toss/WebClient/Style.css =================================================================== --- trunk/Toss/WebClient/Style.css 2010-12-22 09:50:51 UTC (rev 1272) +++ trunk/Toss/WebClient/Style.css 2010-12-30 22:58:00 UTC (rev 1273) @@ -598,13 +598,13 @@ stroke-width: 3px; } -.Game-Chess .model-elem-0 { +.Game-Chess .model-elem-0, .Game-Checkers .model-elem-0 { fill: #d18b47; stroke: #260314; stroke-width: 3px; } -.Game-Chess .model-elem-1 { +.Game-Chess .model-elem-1, .Game-Checkers .model-elem-1 { fill: #ffe4aa; /* #ffce9e; */ stroke: #260314; stroke-width: 3px; Modified: trunk/Toss/WebClient/index.html =================================================================== --- trunk/Toss/WebClient/index.html 2010-12-22 09:50:51 UTC (rev 1272) +++ trunk/Toss/WebClient/index.html 2010-12-30 22:58:00 UTC (rev 1273) @@ -102,6 +102,12 @@ </p> <ul class="plays-list" id="plays-list-Breakthrough"></ul> <p class="game-par"> + <button class="bt" onclick="new_play ('Checkers')">New Game</button> + <a class="game_list" + href="http://en.wikipedia.org/wiki/Checkers">Checkers</a> + </p> + <ul class="plays-list" id="plays-list-Checkers"></ul> + <p class="game-par"> <button class="bt" onclick="new_play ('Chess')">New Game</button> <a class="game_list" href="http://en.wikipedia.org/wiki/Chess">Chess</a> </p> Added: trunk/Toss/examples/Checkers.toss =================================================================== --- trunk/Toss/examples/Checkers.toss (rev 0) +++ trunk/Toss/examples/Checkers.toss 2010-12-30 22:58:00 UTC (rev 1273) @@ -0,0 +1,211 @@ +PLAYERS 1, 2 +DATA depth: 2, adv_ratio: 2 +REL IsFirst(x) = not ex z C(z, x) +REL IsEight(x) = not ex z C(x, z) +REL w(x) = W(x) or Wq(x) +REL b(x) = B(x) or Bq(x) +REL DiagWa (x, y) = ex z (C(x, z) and R(y, z)) +REL DiagBa (x, y) = ex z (C(z, x) and R(z, y)) +REL DiagWb (x, y) = ex z (C(x, z) and R(z, y)) +REL DiagBb (x, y) = ex z (C(z, x) and R(y, z)) +REL DiagW2 (x, y, z) = + (DiagWa (x, y) and DiagWa (y, z)) or (DiagWb (x, y) and DiagWb (y, z)) +REL DiagB2 (x, y, z) = + (DiagBa (x, y) and DiagBa (y, z)) or (DiagBb (x, y) and DiagBb (y, z)) +REL Diag2 (x, y, z) = DiagW2 (x, y, z) or DiagB2 (x, y, z) +REL BeatsW (x, y) = ex z (b(z) and not b(y) and not w(y) and Diag2 (x, z, y)) +REL BeatsB (x, y) = ex z (w(z) and not b(y) and not w(y) and Diag2 (x, z, y)) +REL Da (x, y) = DiagWa (x, y) or DiagBa (x, y) +REL Db (x, y) = DiagWb (x, y) or DiagBb (x, y) +REL FreeDa (x, y) = tc 7 x, y (Da (x, y) and not w(y) and not b(y)) +REL FreeDb (x, y) = tc 7 x, y (Db (x, y) and not w(y) and not b(y)) +REL FreeDWa (x, y) = tc 6 x, y (DiagWa (x, y) and not w(y) and not b(y)) +REL FreeDWb (x, y) = tc 6 x, y (DiagWb (x, y) and not w(y) and not b(y)) +REL FreeDBa (x, y) = tc 6 x, y (DiagBa (x, y) and not w(y) and not b(y)) +REL FreeDBb (x, y) = tc 6 x, y (DiagBb (x, y) and not w(y) and not b(y)) +REL TrDWa (x, y) = ex z (FreeDWa (x, z) and (z = y or DiagWa (z, y))) +REL TrDWb (x, y) = ex z (FreeDWb (x, z) and (z = y or DiagWb (z, y))) +REL TrDBa (x, y) = ex z (FreeDBa (x, z) and (z = y or DiagBa (z, y))) +REL TrDBb (x, y) = ex z (FreeDBb (x, z) and (z = y or DiagBb (z, y))) +REL TDiagW2 (x, y, z) = + (TrDWa (x, y) and DiagWa (y, z)) or (TrDWb (x, y) and DiagWb (y, z)) +REL TDiagB2 (x, y, z) = + (TrDBa (x, y) and DiagBa (y, z)) or (TrDBb (x, y) and DiagBb (y, z)) +REL TDiag2 (x, y, z) = TDiagW2 (x, y, z) or TDiagB2 (x, y, z) +RULE WhiteMove: + [ a, b | W { a } | + vx {a->0.,b->0.}; vy {a->0.,b->0.}; x {a->0.,b->10.}; y {a->0.,b->10.} ] + -> + [ a, b | W { b } | + vx {a->0.,b->0.}; vy {a->0.,b->0.}; x {a->0.,b->10.}; y {a->0.,b->10.} ] + emb w, b pre (not IsEight(b)) and (DiagWa(a, b) or DiagWb(a, b)) + and not ex x, y (W(x) and BeatsW (x, y)) +RULE BlackMove: + [ a, b | B { a } | + vx {a->0.,b->0.}; vy {a->0.,b->0.}; x {a->0.,b->10.}; y {a->0.,b->10.} ] + -> + [ a, b | B { b } | + vx {a->0.,b->0.}; vy {a->0.,b->0.}; x {a->0.,b->10.}; y {a->0.,b->10.} ] + emb w, b pre (not IsFirst(b)) and (DiagBa(a, b) or DiagBb(a, b)) + and not ex x, y (B(x) and BeatsB (x, y)) +RULE WhitePromote: + [ a, b | W { a } | + vx {a->0.,b->0.}; vy {a->0.,b->0.}; x {a->0.,b->10.}; y {a->0.,b->10.} ] + -> + [ a, b | Wq { b } | + vx {a->0.,b->0.}; vy {a->0.,b->0.}; x {a->0.,b->10.}; y {a->0.,b->10.} ] + emb w, b pre (IsEight(b)) and (DiagWa(a, b) or DiagWb(a, b)) + and not ex x, y (W(x) and BeatsW (x, y)) +RULE BlackPromote: + [ a, b | B { a } | + vx {a->0.,b->0.}; vy {a->0.,b->0.}; x {a->0.,b->10.}; y {a->0.,b->10.} ] + -> + [ a, b | Bq { b } | + vx {a->0.,b->0.}; vy {a->0.,b->0.}; x {a->0.,b->10.}; y {a->0.,b->10.} ] + emb w, b pre (IsFirst(b)) and (DiagBa(a, b) or DiagBb(a, b)) + and not ex x, y (B(x) and BeatsB(x, y)) +RULE WhiteQMove: + [ a, b | Wq { a } | + vx {a->0.,b->0.}; vy {a->0.,b->0.}; x {a->0.,b->10.}; y {a->0.,b->10.} ] + -> + [ a, b | Wq { b } | + vx {a->0.,b->0.}; vy {a->0.,b->0.}; x {a->0.,b->10.}; y {a->0.,b->10.} ] + emb w, b pre FreeDa(a, b) or FreeDb(a, b) +RULE BlackQMove: + [ a, b | Bq { a } | + vx {a->0.,b->0.}; vy {a->0.,b->0.}; x {a->0.,b->10.}; y {a->0.,b->10.} ] + -> + [ a, b | Bq { b } | + vx {a->0.,b->0.}; vy {a->0.,b->0.}; x {a->0.,b->10.}; y {a->0.,b->10.} ] + emb w, b pre FreeDa(a, b) or FreeDb(a, b) +RULE WhiteBeat: + [ a, b, c | W { a }; b { b } | + vx {a->0.,b->0.,c->0.}; vy {a->0.,b->0.,c->0.}; + x {a->0.,b->10.,c->20.}; y {a->0.,b->10.,c->20.} ] + -> + [ a, b, c | W { c } | + vx {a->0.,b->0.,c->0.}; vy {a->0.,b->0.,c->0.}; + x {a->0.,b->10.,c->20.}; y {a->0.,b->10.,c->20.} ] + emb w, b pre Diag2 (a, b, c) and not IsEight(c) + post not ex x, y (_new_W(x) and BeatsW (x, y)) +RULE BlackBeat: + [ a, b, c | B { a }; w { b } | + vx {a->0.,b->0.,c->0.}; vy {a->0.,b->0.,c->0.}; + x {a->0.,b->10.,c->20.}; y {a->0.,b->10.,c->20.} ] + -> + [ a, b, c | B { c } | + vx {a->0.,b->0.,c->0.}; vy {a->0.,b->0.,c->0.}; + x {a->0.,b->10.,c->20.}; y {a->0.,b->10.,c->20.} ] + emb w, b pre Diag2 (a, b, c) and not IsFirst(c) + post not ex x, y (_new_B(x) and BeatsB (x, y)) +RULE WhiteBeatPromote: + [ a, b, c | W { a }; b { b } | + vx {a->0.,b->0.,c->0.}; vy {a->0.,b->0.,c->0.}; + x {a->0.,b->10.,c->20.}; y {a->0.,b->10.,c->20.} ] + -> + [ a, b, c | Wq { c } | + vx {a->0.,b->0.,c->0.}; vy {a->0.,b->0.,c->0.}; + x {a->0.,b->10.,c->20.}; y {a->0.,b->10.,c->20.} ] + emb w, b pre Diag2 (a, b, c) and IsEight(c) + post not ex x, y (_new_W(x) and BeatsW (x, y)) +RULE BlackBeatPromote: + [ a, b, c | B { a }; w { b } | + vx {a->0.,b->0.,c->0.}; vy {a->0.,b->0.,c->0.}; + x {a->0.,b->10.,c->20.}; y {a->0.,b->10.,c->20.} ] + -> + [ a, b, c | Bq { c } | + vx {a->0.,b->0.,c->0.}; vy {a->0.,b->0.,c->0.}; + x {a->0.,b->10.,c->20.}; y {a->0.,b->10.,c->20.} ] + emb w, b pre Diag2 (a, b, c) and IsFirst(c) + post not ex x, y (_new_B(x) and BeatsB (x, y)) +RULE WhiteBeatCont: + [ a, b, c | W { a }; b { b } | + vx {a->0.,b->0.,c->0.}; vy {a->0.,b->0.,c->0.}; + x {a->0.,b->10.,c->20.}; y {a->0.,b->10.,c->20.} ] + -> + [ a, b, c | W { c } | + vx {a->0.,b->0.,c->0.}; vy {a->0.,b->0.,c->0.}; + x {a->0.,b->10.,c->20.}; y {a->0.,b->10.,c->20.} ] + emb w, b pre Diag2 (a, b, c) post ex x, y (_new_W(x) and BeatsW (x, y)) +RULE BlackBeatCont: + [ a, b, c | B { a }; w { b } | + vx {a->0.,b->0.,c->0.}; vy {a->0.,b->0.,c->0.}; + x {a->0.,b->10.,c->20.}; y {a->0.,b->10.,c->20.} ] + -> + [ a, b, c | B { c } | + vx {a->0.,b->0.,c->0.}; vy {a->0.,b->0.,c->0.}; + x {a->0.,b->10.,c->20.}; y {a->0.,b->10.,c->20.} ] + emb w, b pre Diag2 (a, b, c) post ex x, y (_new_B(x) and BeatsB (x, y)) +RULE WhiteQBeat: + [ a, b, c | Wq { a }; b { b } | + vx {a->0.,b->0.,c->0.}; vy {a->0.,b->0.,c->0.}; + x {a->0.,b->10.,c->20.}; y {a->0.,b->10.,c->20.} ] + -> + [ a, b, c | Wq { c } | + vx {a->0.,b->0.,c->0.}; vy {a->0.,b->0.,c->0.}; + x {a->0.,b->10.,c->20.}; y {a->0.,b->10.,c->20.} ] + emb w, b pre TDiag2 (a, b, c) +RULE BlackQBeat: + [ a, b, c | Bq { a }; w { b } | + vx {a->0.,b->0.,c->0.}; vy {a->0.,b->0.,c->0.}; + x {a->0.,b->10.,c->20.}; y {a->0.,b->10.,c->20.} ] + -> + [ a, b, c | Bq { c } | + vx {a->0.,b->0.,c->0.}; vy {a->0.,b->0.,c->0.}; + x {a->0.,b->10.,c->20.}; y {a->0.,b->10.,c->20.} ] + emb w, b pre TDiag2 (a, b, c) +LOC 0 { + PLAYER 1 + PAYOFF { + 1: :(ex x w(x)) - :(ex x b(x)); + 2: :(ex x b(x)) - :(ex x w(x)) + } + MOVES [WhiteMove -> 1]; [WhitePromote -> 1]; [WhiteQMove -> 1]; + [WhiteBeat -> 1]; [WhiteBeatPromote -> 1]; [WhiteQBeat -> 1]; + [WhiteBeatCont -> 2] +} +LOC 1 { + PLAYER 2 + PAYOFF { + 1: :(ex x w(x)) - :(ex x b(x)); + 2: :(ex x b(x)) - :(ex x w(x)) + } + MOVES [BlackMove -> 0]; [BlackPromote -> 0]; [BlackQMove -> 0]; + [BlackBeat -> 0]; [BlackBeatPromote -> 0]; [BlackQBeat -> 0]; + [BlackBeatCont -> 3] +} +LOC 2 { + PLAYER 1 + PAYOFF { + 1: :(ex x w(x)) - :(ex x b(x)); + 2: :(ex x b(x)) - :(ex x w(x)) + } + MOVES [WhiteBeat -> 1]; [WhiteBeatPromote -> 1]; [WhiteBeatCont -> 2] +} +LOC 3 { + PLAYER 2 + PAYOFF { + 1: :(ex x w(x)) - :(ex x b(x)); + 2: :(ex x b(x)) - :(ex x w(x)) + } + MOVES [BlackBeat -> 0]; [BlackBeatPromote -> 0]; [BlackBeatCont -> 3] +} +MODEL [ | Wq:1 { }; Bq:1 { } | + ] " + ... ... ... ... + B.. B.. B.. B.. + ... ... ... ... + B.. B.. B.. B.. + ... ... ... ... + B.. B.. B.. B.. + ... ... ... ... + ... ... ... ... + ... ... ... ... + ... ... ... ... + ... ... ... ... + W.. W.. W.. W.. + ... ... ... ... + W.. W.. W.. W.. + ... ... ... ... + W.. W.. W.. W.. +" Added: trunk/Toss/examples/Checkers.tossstyle =================================================================== --- trunk/Toss/examples/Checkers.tossstyle (rev 0) +++ trunk/Toss/examples/Checkers.tossstyle 2010-12-30 22:58:00 UTC (rev 1273) @@ -0,0 +1,6 @@ +nocolor ; +elOPACITY: 20 ; +relOPACITY: 150 ; +arrLENscale: 0.0 ; +W: ~/greencircle.svg; +B: ~/bluecircle.svg; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-22 09:50:57
|
Revision: 1272 http://toss.svn.sourceforge.net/toss/?rev=1272&view=rev Author: lukstafi Date: 2010-12-22 09:50:51 +0000 (Wed, 22 Dec 2010) Log Message: ----------- Loading test games from examples. Modified Paths: -------------- trunk/Toss/Play/GameTest.ml Modified: trunk/Toss/Play/GameTest.ml =================================================================== --- trunk/Toss/Play/GameTest.ml 2010-12-22 00:35:44 UTC (rev 1271) +++ trunk/Toss/Play/GameTest.ml 2010-12-22 09:50:51 UTC (rev 1272) @@ -36,7 +36,7 @@ module StrMap = Structure.StringMap module IntMap = Structure.IntMap -(* Like {!Game.move_str}, but simplified (less data, shortest form). *) +(* Like {!Game.move_str}, but simplified (less data, shorter form). *) let move_str rules struc move = (* let r = List.assoc move.Game.rule rules in *) (* let rhs_struc = r.ContinuousRule.discrete.DiscreteRule.rhs_struc in *) @@ -44,114 +44,13 @@ (* Structure.elem_str rhs_struc r *) string_of_int r ^ ":" ^ Structure.elem_str struc e in let emb = String.concat ", " - (List.sort compare (List.map p_name move.Game.embedding)) in + (List.map p_name (List.sort Pervasives.compare move.Game.embedding)) in move.Game.rule ^ "{" ^ emb ^ "}" let move_gs_str state move = move_str state.Arena.game.Arena.rules state.Arena.struc move -let parse_board_rule init_model ?(rule_model="[ | | ]") lhs rhs precond = - let lhs_struc = struc_of_str (rule_model^" \""^lhs^"\"") in - let rhs_struc = struc_of_str (rule_model^" \""^rhs^"\"") in - let rule_s = List.map2 (fun x y -> x, y) - (Structure.Elems.elements lhs_struc.Structure.elements) - (Structure.Elems.elements rhs_struc.Structure.elements) in - (* - let update = Aux.concat_map - (fun e -> - [("x", Structure.elem_str rhs_struc e), - Term.FVar ("x", Structure.elem_str rhs_struc e); - ("y", Structure.elem_str rhs_struc e), - Term.FVar ("y", Structure.elem_str rhs_struc e)]) - (Structure.Elems.elements lhs_struc.Structure.elements) in - let dynamics = Aux.concat_map - (fun e -> - [("x", Structure.elem_str rhs_struc e), Term.Const (0.); - ("y", Structure.elem_str rhs_struc e), Term.Const (0.)]) - (Structure.Elems.elements lhs_struc.Structure.elements) in - *) - let emb_rels = - Structure.StringMap.fold (fun rel arity acc -> - if arity = 1 && DiscreteRule.special_rel_of rel = None - then rel::acc else acc) - lhs_struc.Structure.rel_signature [] in - let pre = formula_of_str precond in - let discr_spec pre = { - DiscreteRule.lhs_struc = lhs_struc; - rhs_struc = rhs_struc; - rule_s = rule_s; - emb_rels = emb_rels; - pre = pre; - } in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) - rhs_struc.Structure.rel_signature [] in - ContinuousRule.make_rule signat [] (discr_spec (Formula.And [])) [] [] - (* dynamics update *) ~pre () - -let board_game ?(zero_sum=true) init_board ?rule_model rules1 rules2 - ?payoffs win1 win2 = - let init_board = struc_of_str init_board in - let rules1 = List.map (fun (lhs, rhs) -> - parse_board_rule init_board ?rule_model lhs rhs - ("not (" ^ win2 ^ ")")) rules1 in - let rules2 = List.map (fun (lhs, rhs) -> - parse_board_rule init_board ?rule_model lhs rhs - ("not (" ^ win1 ^ ")")) rules2 in - let rules1 = Array.mapi - (fun i rule -> string_of_int (i + 1), rule) - (Array.of_list rules1) in - let rules2 = Array.mapi - (fun i rule -> string_of_int (i + 1 + Array.length rules1), rule) - (Array.of_list rules2) in - let rules = Array.to_list (Array.append rules1 rules2) in - let payoffs = - match payoffs with - | Some (payoff0, payoff1) -> - [|real_expr_of_str payoff0; - real_expr_of_str payoff1|] - | None -> - if zero_sum then - let payoff0 = ":("^win1^") - :("^win2^")" - and payoff1 = ":("^win2^") - :("^win1^")" in - [|real_expr_of_str payoff0; - real_expr_of_str payoff1|] - else - [|Formula.Char (formula_of_str win1); - Formula.Char (formula_of_str win2)|] in - let location0 = { - Arena.id = 0; - player = 0; - payoffs = payoffs; - payoffs_pp = - Array.map Solver.M.register_real_expr payoffs; - moves = Array.to_list (Array.map (fun (rname, rule) -> - {Arena.rule = rname; time_in = 0.1, 0.1; parameters_in = []}, 1) - rules1); - } in - let location1 = { - Arena.id = 1; - player = 1; - payoffs = payoffs; - payoffs_pp = - Array.map Solver.M.register_real_expr payoffs; - moves = Array.to_list (Array.map (fun (rname, rule) -> - {Arena.rule = rname; time_in = 0.1, 0.1; parameters_in = []}, 0) - rules2); - } in { - Arena.game = { - Arena.rules = rules; - player_names = ["1", 0; "2", 1]; - defined_rels = []; - graph = [|location0; location1|]; - num_players = 2}; - struc = init_board; - time = 0.0; - cur_loc = 0; - data = []; - } - -let update_game (horizon, adv_ratio, game) state cur_loc = +let update_game (lazy (horizon, adv_ratio, game)) state cur_loc = let state = struc_of_str state in horizon, adv_ratio, {game with Arena.struc = state; cur_loc = cur_loc} @@ -219,233 +118,17 @@ done; r -(* board_game ?(zero_sum=true) init_board ?rule_model rules1 rules2 - ?payoffs win1 win2 *) let breakthrough_game = - None, 2.0, board_game -"[ | | ] \" - ... ... ... ... - B B..B B..B B..B B.. - ... ... ... ... - B..B B..B B..B B..B - ... ... ... ... - ... ... ... ... - ... ... ... ... - ... ... ... ... - ... ... ... ... - ... ... ... ... - ... ... ... ... - ... ... ... ... - ... ... ... ... - W W..W W..W W..W W.. - ... ... ... ... - W..W W..W W..W W..W -\"" - ~rule_model:"[ | W:1 { }; B:1 { } | ]" - [ -(" - -?B ? - -? W -", -" - -W ? - -? . -"); -(" - -. - -W -", -" - -W - -. -"); -(" - -? ?B - -W ? -", -" - -? W - -. ? -"); - ] - [ -(" - -B ? - -? ?W -", -" - -. ? - -? B -"); -(" - -B - -. -", -" - -. - -B -"); -(" - -? B - -?W ? -", -" - -? . - -B ? -"); - ] - "ex x (W(x) and not ex y C(x, y))" - "ex x (B(x) and not ex y C(y, x))" + lazy (None, 2.0, state_of_file "./examples/Breakthrough.toss") let tictactoe_game = - None, 4.0, board_game - "[ | P:1 { }; Q:1 { } | ] \" - - . . . - - . . . - - . . . -\"" -~rule_model:"[ | P:1 { }; Q:1 { } | ]" -[" - -. -", -" - -P -"] [" - -. -", -" - -Q -"] - winPxyz winQxyz + lazy (None, 4.0, state_of_file "./examples/Tic-Tac-Toe.toss") let gomoku8x8_game = - None, 4.0, board_game -"[ | P:1 { }; Q:1 { } | ] \" - ... ... ... ... - ... ... ... ... -... ... ... ... -... ... ... ... - ... ... ... ... - ... ... ... ... -... ... ... ... -... ... ... ... - ... ... ... ... - ... ... ... ... -... ... ... ... -... ... ... ... - ... ... ... ... - ... ... ... ... -... ... ... ... -... ... ... ... -\"" - ~rule_model:"[ | P:1 { }; Q:1 { } | ]" -[" - -. -", -" - -P -"] [" - -. -", -" - -Q -"] - winPvwxyz winQvwxyz + lazy (None, 4.0, state_of_file "./examples/Gomoku.toss") let gomoku19x19_game = - None, 4.0, board_game -"[ | P:1 { }; Q:1 { } | ] \" - - ....................................................... - . . . . . . . . . . . . . . . . . . . - ....................................................... - . . . . . . . . . . . . . . . . . . . - ....................................................... - . . . . . . . . . . . . . . . . . . . - ....................................................... - . . . . . . . . . . . . . . . . . . . - ....................................................... - . . . . . . . . . . . . . . . . . . . - ....................................................... - . . . . . . . . . . . . . . . . . . . - ....................................................... - . . . . . . . . . . . . . . . . . . . - ....................................................... - . . . . . . . . . . . . . . . . . . . - ....................................................... - . . . . . . . . . . . . . . . . . . . - ....................................................... - . . . . . . . . . . . . . . . . . . . - ....................................................... - . . . . . . . . . . . . . . . . . . . - ....................................................... - . . . . . . . . . . . . . . . . . . . - ....................................................... - . . . . . . . . . . . . . . . . . . . - ....................................................... - . . . . . . . . . . . . . . . . . . . - ....................................................... - . . . . . . . . . . . . . . . . . . . - ....................................................... - . . . . . . . . . . . . . . . . . . . - ....................................................... - . . . . . . . . . . . . . . . . . . . - ....................................................... - . . . . . . . . . . . . . . . . . . . - ....................................................... -\"" - ~rule_model:"[ | P:1 { }; Q:1 { } | ]" -[" - -. -", -" - -P -"] [" - -. -", -" - -Q -"] - winPvwxyz winQvwxyz + lazy (None, 4.0, state_of_file "./examples/Gomoku19x19.toss") let breakthrough_heur_adv adv_ratio = let expanded_win1 = @@ -627,9 +310,9 @@ (move_opt <> None); ); - "play: chess random play" >:: + "play: chess begin random play" >:: (fun () -> - let horizon, heur_adv_ratio, state = + let _, heur_adv_ratio, state = Lazy.force chess_game in let struc = state.Arena.struc in let game = state.Arena.game in @@ -640,7 +323,7 @@ let init_state = Game.initial_state play struc in (* let endstate,payoff = *) ignore (Game.play ~grid_size:Game.cGRID_SIZE - ~set_timer:360 ?horizon play init_state) (* in *) + ~set_timer:360 ~horizon:30 play init_state) (* in *) (* nothing to assert -- just check halting without exceptions *) (* Printf.printf "Chess random play horizon=30 ended in:\n%s\n%!" @@ -700,7 +383,7 @@ "chess draw" >:: (fun () -> let horizon, heur_adv_ratio, state = - update_game (Lazy.force chess_game) + update_game chess_game "[a1, b1, c1, d1, e1, f1, g1, h1, a2, b2, c2, d2, e2, f2, g2, h2, a3, b3, c3, d3, e3, f3, g3, h3, a4, b4, c4, d4, e4, f4, g4, h4, a5, b5, c5, d5, e5, f5, g5, h5, a6, b6, c6, d6, e6, f6, g6, h6, a7, b7, c7, d7, e7, f7, g7, h7, a8, b8, c8, d8, e8, f8, g8, h8 | D1 {(a1, b2); (b1, c2); (c1, d2); (d1, e2); (e1, f2); (f1, g2); (g1, h2); (a2, b3); (b2, a1); (b2, c3); (c2, b1); (c2, d3); (d2, c1); (d2, e3); (e2, d1); (e2, f3); (f2, e1); (f2, g3); (g2, f1); (g2, h3); (h2, g1); (a3, b4); (b3, a2); (b3, c4); (c3, b2); (c3, d4); (d3, c2); (d3, e4); (e3, d2); (e3, f4); (f3, e2); (f3, g4); (g3, f2); (g3, h4); (h3, g2); (a4, b5); (b4, a3); (b4, c5); (c4, b3); (c4, d5); (d4, c3); (d4, e5); (e4, d3); (e4, f5); (f4, e3); (f4, g5); (g4, f3); (g4, h5); (h4, g3); (a5, b6); (b5, a4); (b5, c6); (c5, b4); (c5, d6); (d5, c4); (d5, e6); (e5, d4); (e5, f6); (f5, e4); (f5, g6); (g5, f4); (g5, h6); (h5, g4); (a6, b7); (b6, a5); (b6, c7); (c6, b5); (c6, d7); (d6, c5); (d6, e7); (e6, d5); (e6, f7); (f6, e5); (f6, g7); (g6, f5); (g6, h7); (h6, g5); (a7, b8); (b7, a6); (b7, c8); (c7, b6); (c7, d8); (d7, c6); (d7, e8); (e7, d6); (e7, f8); (f7, e6); (f7, g8); (g7, f6); (g7, h8); (h7, g6); (b8, a7); (c8, b7); (d8, c7); (e8, d7); (f8, e7); (g8, f7); (h8, g7)}; D2 {(b1, a2); (c1, b2); (d1, c2); (e1, d2); (f1, e2); (g1, f2); (h1, g2); (a2, b1); (b2, c1); (b2, a3); (c2, d1); (c2, b3); (d2, e1); (d2, c3); (e2, f1); (e2, d3); (f2, g1); (f2, e3); (g2, h1); (g2, f3); (h2, g3); (a3, b2); (b3, c2); (b3, a4); (c3, d2); (c3, b4); (d3, e2); (d3, c4); (e3, f2); (e3, d4); (f3, g2); (f3, e4); (g3, h2); (g3, f4); (h3, g4); (a4, b3); (b4, c3); (b4, a5); (c4, d3); (c4, b5); (d4, e3); (d4, c5); (e4, f3); (e4, d5); (f4, g3); (f4, e5); (g4, h3); (g4, f5); (h4, g5); (a5, b4); (b5, c4); (b5, a6); (c5, d4); (c5, b6); (d5, e4); (d5, c6); (e5, f4); (e5, d6); (f5, g4); (f5, e6); (g5, h4); (g5, f6); (h5, g6); (a6, b5); (b6, c5); (b6, a7); (c6, d5); (c6, b7); (d6, e5); (d6, c7); (e6, f5); (e6, d7); (f6, g5); (f6, e7); (g6, h5); (g6, f7); (h6, g7); (a7, b6); (b7, c6); (b7, a8); (c7, d6); (c7, b8); (d7, e6); (d7, c8); (e7, f6); (e7, d8); (f7, g6); (f7, e8); (g7, h6); (g7, f8); (h7, g8); (a8, b7); (b8, c7); (c8, d7); (d8, e7); (e8, f7); (f8, g7); (g8, h7)}; bB:1 {}; wB:1 {}; wN:1 {}; wP:1 {}; wQ:1 {}; wR:1 {} | ] \" ... ... ... ... ... ... +bN ... @@ -748,17 +431,17 @@ "matching: breakthrough suggest start" >:: (fun () -> let horizon, heur_adv_ratio, state = - breakthrough_game in - let r = List.assoc "1" state.Arena.game.Arena.rules in + Lazy.force breakthrough_game in + let r = List.assoc "WhiteDiag" state.Arena.game.Arena.rules in let matches = ContinuousRule.matches state.Arena.struc r in - assert_bool "Move to the left should be possible." + assert_bool "Diagonal move should be possible." (matches <> []) ); "gomoku8x8 suggest" >:: (fun () -> let horizon, heur_adv_ratio, state = - gomoku8x8_game in + Lazy.force gomoku8x8_game in (* Game.set_debug_level 2; *) let move_opt = (let p,ps = Game.initialize_default state ~heur_adv_ratio ?horizon ~loc:0 ~effort:2 @@ -818,7 +501,7 @@ \"" 1 in (* TODO: replace with easy_case after monotonic heur done *) easy_case state 1 "Q should block for tie" - (fun mov_s -> "2{1:a1}" = mov_s)); + (fun mov_s -> "Circle{1:a1}" = mov_s)); "tictactoe suggest optimal single" >:: (fun () -> @@ -832,7 +515,7 @@ . . P \"" 1 in easy_case state 1 "Q play the middle for tie" - (fun mov_s -> "2{1:b2}" = mov_s)); + (fun mov_s -> "Circle{1:b2}" = mov_s)); "tictactoe suggest optimal multi" >:: (fun () -> @@ -849,7 +532,7 @@ easy_case state 1 ("Q should play the corner for tie"^ " (heuristic still ignores monotonicity?)") (fun mov_s -> List.mem mov_s - ["2{1:a1}"; "2{1:a3}"; "2{1:c1}"; "2{1:c3}"])); + ["Circle{1:a1}"; "Circle{1:a3}"; "Circle{1:c1}"; "Circle{1:c3}"])); "tictactoe suggest avoid endgame diagonal" >:: (fun () -> @@ -864,7 +547,7 @@ \"" 1 in (* TODO: replace with easy_case after monotonic heur done *) easy_case state 1 "Q should block diagonal" - (fun mov_s -> "2{1:a1}" = mov_s)); + (fun mov_s -> "Circle{1:a1}" = mov_s)); "tictactoe suggest avoid endgame straight" >:: (fun () -> @@ -879,7 +562,7 @@ \"" 1 in (* TODO: replace with easy_case after monotonic heur done *) easy_case state 1 "Q should block straight" - (fun mov_s -> "2{1:b1}" = mov_s); + (fun mov_s -> "Circle{1:b1}" = mov_s); ); "tictactoe suggest win" >:: @@ -894,7 +577,7 @@ Q . Q \"" 1 in easy_case state 1 "Q should win" - (fun mov_s -> "2{1:b1}" = mov_s)); + (fun mov_s -> "Circle{1:b1}" = mov_s)); "breakthrough suggest avoid endgame" >:: (fun () -> @@ -920,7 +603,8 @@ easy_case state 0 "W shouldn't move from b1" (fun mov_s -> not (List.mem mov_s - ["2{2:b2, 1:b1}"; "1{4:b2, 2:b1, 3:a2, 1:a1}"]))); + ["WhiteStraight{1:b1, 2:b2}"; + "WhiteDiag{1:b1, 2:a2}"; "WhiteDiag{1:b1, 2:c2}"]))); "breakthrough suggest endgame" >:: (fun () -> @@ -944,7 +628,7 @@ W.. ...W W..W W..W \"" 1 in easy_case state 1 "B should attack left" - (fun mov_s -> "6{1:a2, 2:b2, 3:a3, 4:b3}" = mov_s)); + (fun mov_s -> "BlackDiag{1:b3, 2:a2}" = mov_s)); "breakthrough suggest midgame" >:: (fun () -> @@ -969,7 +653,7 @@ \"" 0 in (* white move should beat the lower black *) easy_case state 0 "W should beat the lower B" (* or medium *) - (fun mov_s -> "3{1:e3, 2:f3, 3:e4, 4:f4}" = mov_s)); + (fun mov_s -> "WhiteDiag{1:e3, 2:f4}" = mov_s)); "breakthrough suggest adv_ratio" >:: (fun () -> @@ -992,10 +676,10 @@ ... ... ... ... W..W W..W W..W W..W \"" 0 in - (* white move should beat the lower black *) easy_case state 0 "W should play cool" - (fun mov_s -> mov_s <> "3{1:e4, 2:f4, 3:e5, 4:f5}" - && mov_s <> "2{1:d4, 2:e4, 3:d5, 4:e5}")); + (fun mov_s -> + mov_s <> "WhiteDiag{1:e4, 2:f5}" + && mov_s <> "WhiteDiag{1:e4, 2:d5}")); "breakthrough suggest depth" >:: (fun () -> @@ -1018,11 +702,11 @@ ... ... ... ... W..W W..W W..W W..W \"" 0 in - (* white move should beat the lower black *) medium_case state 0 "W should not lose the piece" - (fun mov_s -> mov_s <> "3{1:d5, 2:e5, 3:d6, 4:e6}" - && mov_s <> "2{1:c5, 2:d5, 3:c6, 4:d6}" - && mov_s <> "1{1:d5, 2:d6}")); + (fun mov_s -> + mov_s <> "WhiteDiag{1:d5, 2:e6}" + && mov_s <> "WhiteDiag{1:d5, 2:c6}" + && mov_s <> "WhiteStraight{1:d5, 2:d6}")); "gomoku8x8 avoid endgame" >:: @@ -1047,7 +731,7 @@ ... ... ... ... \"" 0 in easy_case state 0 "P should block" - (fun mov_s -> "1{1:b5}" = mov_s); + (fun mov_s -> "Cross{1:b5}" = mov_s); let state = update_game gomoku8x8_game "[ | | ] \" @@ -1069,7 +753,7 @@ ... ... ... ... \"" 0 in easy_case state 0 "P should block with line" - (fun mov_s -> "1{1:f7}" = mov_s); + (fun mov_s -> "Cross{1:f7}" = mov_s); ); @@ -1096,7 +780,7 @@ ... ... ... ... \"" 0 in easy_case state 0 "P should block" - (fun mov_s -> "1{1:a3}" = mov_s); + (fun mov_s -> "Cross{1:a3}" = mov_s); ); @@ -1123,7 +807,7 @@ ... ... ...Q ... \"" 0 in easy_case state 0 "should block the open line" - (fun mov_s -> "1{1:e7}" = mov_s); + (fun mov_s -> "Cross{1:e7}" = mov_s); ); "gomoku8x8 attack" >:: @@ -1148,7 +832,7 @@ ... ... Q.. ... \"" 0 in easy_case state 0 "should attack the diagonal" - (fun mov_s -> "1{1:d4}" = mov_s); + (fun mov_s -> "Cross{1:d4}" = mov_s); ); ] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-22 00:35:50
|
Revision: 1271 http://toss.svn.sourceforge.net/toss/?rev=1271&view=rev Author: lukaszkaiser Date: 2010-12-22 00:35:44 +0000 (Wed, 22 Dec 2010) Log Message: ----------- Set depth to 3 in breakthrough. Modified Paths: -------------- trunk/Toss/Play/GDL.ml Modified: trunk/Toss/Play/GDL.ml =================================================================== --- trunk/Toss/Play/GDL.ml 2010-12-21 23:54:58 UTC (rev 1270) +++ trunk/Toss/Play/GDL.ml 2010-12-22 00:35:44 UTC (rev 1271) @@ -66,7 +66,7 @@ game_description := game_descr; player_name_terms := [|Const "WHITE"; Const "BLACK"|]; let effort, horizon, heur_adv_ratio = - 2, 100, 2.0 in + 3, 100, 2.0 in effort, horizon, heur_adv_ratio let initialize_game = This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-21 23:55:04
|
Revision: 1270 http://toss.svn.sourceforge.net/toss/?rev=1270&view=rev Author: lukstafi Date: 2010-12-21 23:54:58 +0000 (Tue, 21 Dec 2010) Log Message: ----------- GDL breakthrough (tentative hardcoded), minor bugfix Modified Paths: -------------- trunk/Toss/Play/GDL.ml Modified: trunk/Toss/Play/GDL.ml =================================================================== --- trunk/Toss/Play/GDL.ml 2010-12-21 23:42:15 UTC (rev 1269) +++ trunk/Toss/Play/GDL.ml 2010-12-21 23:54:58 UTC (rev 1270) @@ -134,6 +134,7 @@ let translate_move_breakthrough rule emb new_state = let struc = new_state.Arena.struc in + let emb = List.sort Pervasives.compare emb in match emb with | [(_,a); (_,b)] -> let a, b = if rule = "BlackStraight" then b, a else a, b in This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-21 23:42:22
|
Revision: 1269 http://toss.svn.sourceforge.net/toss/?rev=1269&view=rev Author: lukaszkaiser Date: 2010-12-21 23:42:15 +0000 (Tue, 21 Dec 2010) Log Message: ----------- WebClient improvements, Gc compact on NOOP, more readable definitions of Tic-Tac-Toe and Gomoku. Modified Paths: -------------- trunk/Toss/Play/Server.ml trunk/Toss/WebClient/Connect.js trunk/Toss/WebClient/DefaultStyle.js trunk/Toss/WebClient/Handler.py trunk/Toss/WebClient/Main.js trunk/Toss/WebClient/README trunk/Toss/WebClient/Style.css trunk/Toss/WebClient/Wrapper.py trunk/Toss/WebClient/index.html trunk/Toss/examples/Gomoku.toss trunk/Toss/examples/Tic-Tac-Toe.toss Modified: trunk/Toss/Play/Server.ml =================================================================== --- trunk/Toss/Play/Server.ml 2010-12-21 23:14:48 UTC (rev 1268) +++ trunk/Toss/Play/Server.ml 2010-12-21 23:42:15 UTC (rev 1269) @@ -354,8 +354,7 @@ memory = memory; }); - if GDL.our_turn !state - then + if GDL.our_turn !state then ( let time_used = int_of_float time_started - int_of_float (ceil (Sys.time ())) in let p, ps = @@ -376,9 +375,11 @@ let msg_len = String.length mov_msg in "HTTP/1.0 200 OK\r\nContent-type: text/acl\r\nContent-length: " ^ string_of_int msg_len ^ "\r\n\r\n" ^ mov_msg - else + ) else ( + Gc.compact (); "HTTP/1.0 200 OK\r\nContent-type: text/acl\r\nContent-length: " ^ "4\r\n\r\nNOOP" + ) | Aux.Right (GDL.Stop (_, actions)) -> @@ -460,7 +461,7 @@ in if !debug_level > 0 then ( Printf.printf "Resp-time: %F\n%!" (Sys.time () -. time_started); - print_endline ("Repl: " ^ resp ^ "\n"); + print_endline ("\nRepl: " ^ resp ^ "\n"); ); output_string out_ch (resp ^ "\n"); flush out_ch; Modified: trunk/Toss/WebClient/Connect.js =================================================================== --- trunk/Toss/WebClient/Connect.js 2010-12-21 23:14:48 UTC (rev 1268) +++ trunk/Toss/WebClient/Connect.js 2010-12-21 23:42:15 UTC (rev 1269) @@ -21,12 +21,11 @@ var SUGGESTED_ELEM_SIZEX = 25; // suggested size of elements var SUGGESTED_ELEM_SIZEY = 25; // suggested size of elements -var CACHED_MOVES = "" - var DIM_STR = "" var ELEM_STR = "" var RELS_STR = "" var MOVES_STR = "" +var PAYOFF_STR = "" // Helper function: sign of a number. @@ -36,11 +35,6 @@ else { return (0); } } -// Clears cached moves. -function clear_move_cache () { - CACHED_MOVES = ""; -} - function set_info (info) { var res_arr = []; res_arr = info.split("$"); @@ -48,7 +42,13 @@ DIM_STR = res_arr[0]; ELEM_STR = res_arr[1]; RELS_STR = res_arr[2]; - MOVES_STR = res_arr[3]; + if (res_arr[3].substring(0, 1) == "(") { + MOVES_STR = res_arr[3]; + PAYOFF_STR = ""; + } else { + MOVES_STR = ""; + PAYOFF_STR = res_arr[3]; + }; var dim = strip('(', ')', DIM_STR).split(','); MODEL_MAXX = parseFloat(strip(' ', ' ', dim[0])); MODEL_MINX = parseFloat(strip(' ', ' ', dim[1])); @@ -56,7 +56,6 @@ MODEL_MINY = parseFloat(strip(' ', ' ', dim[3])); MODEL_WIDTH = Math.max (SVG_WIDTH / 100, (MODEL_MAXX - MODEL_MINX)); MODEL_HEIGHT = Math.max (SVG_HEIGHT / 100, (MODEL_MAXY - MODEL_MINY)); - return (true); } @@ -130,15 +129,16 @@ // Get moves applicable to [elem] in a game. -function get_moves (elem) { - if (CACHED_MOVES == "") { - CACHED_MOVES = MOVES_STR - } - var all_moves = convert_python_list (';', CACHED_MOVES); +function get_moves (elem, other) { + var all_moves = convert_python_list (';', MOVES_STR); var elem_moves = [] for (i = 0; i < all_moves.length; i++) { if (all_moves[i].indexOf(elem) >= 0) { - elem_moves.push(all_moves[i]) + if (other == "") { + elem_moves.push(all_moves[i]) + } else if (all_moves[i].indexOf(other) >= 0) { + elem_moves.push(all_moves[i]) + } } } return (elem_moves) Modified: trunk/Toss/WebClient/DefaultStyle.js =================================================================== --- trunk/Toss/WebClient/DefaultStyle.js 2010-12-21 23:14:48 UTC (rev 1268) +++ trunk/Toss/WebClient/DefaultStyle.js 2010-12-21 23:42:15 UTC (rev 1269) @@ -37,7 +37,7 @@ var DEFbishop = '<g transform="translate(-22.5,-22.5)"> \ <path \ d="M 9,36 C 12.385,35.028 19.115,36.431 22.5,34 C 25.885,36.431 32.615,35.028 36,36 C 36,36 37.646,36.542 39,38 C 38.323,38.972 37.354,38.986 36,38.5 C 32.615,37.528 25.885,38.958 22.5,37.5 C 19.115,38.958 12.385,37.528 9,38.5 C 7.6459,38.986 6.6771,38.972 6,38 C 7.3541,36.055 9,36 9,36 z " \ - style="stroke-linecap:butt;" class="chess-path-Bx" /> \ + style="stroke-linecap:butt;" class="chess-path-B" /> \ <path \ d="M 15,32 C 17.5,34.5 27.5,34.5 30,32 C 30.5,30.5 30,30 30,30 C 30,27.5 27.5,26 27.5,26 C 33,24.5 33.5,14.5 22.5,10.5 C 11.5,14.5 12,24.5 17.5,26 C 17.5,26 15,27.5 15,30 C 15,30 14.5,30.5 15,32 z " \ style="stroke-linecap:butt;" class="chess-path-B" /> \ @@ -65,7 +65,7 @@ style="stroke-linecap:butt;" class="chess-path-Bx" /> \ <path \ d="M 12,36 L 12,32 L 33,32 L 33,36 L 12,36 z " \ - style="stroke-linecap:butt;" class="chess-path-Bx" /> \ + style="stroke-linecap:butt;" class="chess-path-B" /> \ <path \ d="M 11,14 L 11,9 L 15,9 L 15,11 L 20,11 L 20,9 L 25,9 L 25,11 L 30,11 L 30,9 L 34,9 L 34,14" \ style="stroke-linecap:butt;" class="chess-path-B" /> \ @@ -77,7 +77,7 @@ style="stroke-linecap:butt;" class="chess-path-B" /> \ <path \ d="M 31,29.5 L 32.5,32 L 12.5,32 L 14,29.5" \ - class="chess-path-Bx" /> \ + class="chess-path-B" /> \ <path \ d="M 11,14 L 34,14" \ class="chess-path-D" /> \ @@ -122,12 +122,12 @@ </g>'; var DEFking = '<g transform="translate(-22.5,-22.5)"> \ - <path d="M 22.5,11.625 L 22.5,6" class="chess-path-D" /> \ + <path d="M 22.5,11.625 L 22.5,6" class="chess-path-B" /> \ <path d="M 22.5,25 C 22.5,25 27,17.5 25.5,14.5 C 25.5,14.5 24.5,12 22.5,12 C 20.5,12 19.5,14.5 19.5,14.5 C 18,17.5 22.5,25 22.5,25" \ style="fill:stroke-linecap:butt;" class="chess-path-B" /> \ <path d="M 11.5,37 C 17,40.5 27,40.5 32.5,37 L 32.5,30 C 32.5,30 41.5,25.5 38.5,19.5 C 34.5,13 25,16 22.5,23.5 L 22.5,27 L 22.5,23.5 C 19,16 9.5,13 6.5,19.5 C 3.5,25.5 11.5,29.5 11.5,29.5 L 11.5,37 z " \ - class="chess-path-D" /> \ - <path d="M 20,8 L 25,8" class="chess-path-D" /> \ + class="chess-path-B" /> \ + <path d="M 20,8 L 25,8" class="chess-path-B" /> \ <path d="M 11.5,29.5 C 17,27 27,27 32.5,30" class="chess-path-D" /> \ <path d="M 11.5,37 C 17,34.5 27,34.5 32.5,37" \ class="chess-path-D" /> \ @@ -136,6 +136,20 @@ </g>'; +function is_int (s) { + return (parseInt(s).toString() == s) +} + +// To draw chess board we distinguish even/odd placed elements. +function elem_class (elem) { + var elem_cl = "model-elem"; + if (is_int (elem.substring(1))) { + var psum = elem.charCodeAt(0) + parseInt (elem.substring(1)); + elem_cl = "model-elem-" + (psum % 2); + }; + return (elem_cl); +} + // Draw the element [elem]. function draw_elem (elem) { var pos = ELEM_POS[elem]; @@ -145,7 +159,7 @@ ["width", 2 * SUGGESTED_ELEM_SIZEX], ["height", 2 * SUGGESTED_ELEM_SIZEX], ["id", "elem_" + elem], - ["class", "model-elem"], + ["class", elem_class(elem)], ["onclick", ("handle_elem_click('" + elem + "')")]] ); } @@ -159,7 +173,7 @@ // Unhighlight the element [elem]. function unhighlight_elem (elem) { var e = document.getElementById ("elem_" + elem); - e.setAttribute ("class", "model-elem"); + e.setAttribute ("class", elem_class(elem)); } // Draw relation [rel_name] between elements [args]. Modified: trunk/Toss/WebClient/Handler.py =================================================================== --- trunk/Toss/WebClient/Handler.py 2010-12-21 23:14:48 UTC (rev 1268) +++ trunk/Toss/WebClient/Handler.py 2010-12-21 23:42:15 UTC (rev 1269) @@ -92,7 +92,9 @@ dim_s = str(client.model.get_dim()) model_s = str(client.model.get_elems_with_pos()) rels_s = str(client.model.get_rels_simple()) - moves_s = str(client.cur_moves()) + moves = client.cur_moves() + moves_s = str(moves) + if (len(moves) == 0): moves_s = client.get_payoffs() return (dim_s + "$" + model_s + "$" + rels_s + "$" + moves_s) def get_free_id (db): Modified: trunk/Toss/WebClient/Main.js =================================================================== --- trunk/Toss/WebClient/Main.js 2010-12-21 23:14:48 UTC (rev 1268) +++ trunk/Toss/WebClient/Main.js 2010-12-21 23:42:15 UTC (rev 1269) @@ -14,6 +14,8 @@ var FULL_OPNT_LEN = 0; var CUR_OPNT_START = 0; +var LAST_CLICKED_ELEM = ""; + // Get model information from server. function get_model_info () { get_elems_with_pos (); @@ -44,7 +46,7 @@ // Clear whole svg box. function clear_svg () { - clear_move_cache (); + LAST_CLICKED_ELEM = ""; ELEM_COUNTERS = {}; CUR_MOVE = ""; CUR_ELEMS = []; @@ -60,6 +62,13 @@ get_model_info (); create_svg_box (SVG_MARGINX, SVG_MARGINY, "board"); draw_model (); + if (PAYOFF_STR == "") { + document.getElementById('movebt').innerHTML = "Make move:"; + document.getElementById('cur-move').innerHTML = "none"; + } else { + document.getElementById('movebt').innerHTML = "Payoffs:"; + document.getElementById('cur-move').innerHTML = PAYOFF_STR; + } document.getElementById("working").style.display = "none"; } @@ -79,6 +88,7 @@ // Helper function: highlight move, unhighlight old, save current. function show_move (m) { var m_act = get_move_elems (m); + m_act.sort (); var m_rule = m.substring (m.indexOf("},")+4, m.lastIndexOf(',')-1); for (var i = 0; i < CUR_ELEMS.length; i++) { unhighlight_elem (CUR_ELEMS[i]); @@ -91,7 +101,7 @@ document.getElementById('cur-move').innerHTML = "none"; } else { document.getElementById('cur-move').innerHTML = - m_rule + ': ' + m_str; + m_str.replace (/,/g, " — ") + " (" + m_rule + ")" } CUR_ELEMS = m_act; CUR_MOVE = m.toString(); @@ -99,14 +109,28 @@ // Handler for clicks on elements. function handle_elem_click (elem) { - var moves = get_moves (elem); + var moves = get_moves (elem, LAST_CLICKED_ELEM); + if (moves.length == 0) { + LAST_CLICKED_ELEM = ""; + moves = get_moves (elem, LAST_CLICKED_ELEM); + }; if (moves.length > ELEM_COUNTERS[elem]) { show_move (moves[ELEM_COUNTERS[elem]]); ELEM_COUNTERS[elem] += 1; } else if (moves.length > 0) { show_move (moves[0]); ELEM_COUNTERS[elem] = 1; - } + }; + if (moves.length > 1 && LAST_CLICKED_ELEM == "") { + for (var i = 0; i < CUR_ELEMS.length; i++) { + unhighlight_elem (CUR_ELEMS[i]); + } + document.getElementById('cur-move').innerHTML = elem + " — ?" + highlight_elem (elem); + CUR_ELEMS = [elem]; + CUR_MOVE = ""; + }; + LAST_CLICKED_ELEM = elem; } function play_py_id (i) { @@ -160,16 +184,18 @@ function game_click (game) { - document.getElementById("welcome").style.display = "none"; - document.getElementById("game-disp").style.display = "none"; - document.getElementById("plays").style.display = "none"; - GAME_NAME = game; - if (game == "Tic-Tac-Toe") { // bigger margins needed - create_svg_box (130, 130, "board"); - } else { - create_svg_box (40, 40, "board"); - } - document.getElementById("game-disp").style.display = "block"; + document.getElementById("welcome").style.display = "none"; + document.getElementById("game-disp").style.display = "none"; + document.getElementById("plays").style.display = "none"; + GAME_NAME = game; + if (game == "Tic-Tac-Toe") { // bigger margins needed + create_svg_box (130, 130, "board"); + } else { + create_svg_box (40, 40, "board"); + } + var gd = document.getElementById("game-disp"); + gd.style.display = "block"; + gd.setAttribute ("class", "Game-" + game); } function play_click (game, play_id, pi) { @@ -198,13 +224,11 @@ document.getElementById("working").style.display = "block"; var info = srv("MOVE_PLAY", 'c, '+ CUR_MOVE +', '+ play_py_id (CUR_PLAY_I)); set_info (info); - clear_move_cache (); CUR_MOVE = ""; CUR_ELEMS = []; ELEM_COUNTERS = {}; document.getElementById("cur-player").innerHTML = disp_name(PLAYS[CUR_PLAY_I][(m + 1) % 2]); - document.getElementById('cur-move').innerHTML = "none"; document.getElementById("working").style.display = "none"; full_redraw (); PLAYS[CUR_PLAY_I][3] = parseInt(PLAYS[CUR_PLAY_I][3]) + 1; @@ -214,8 +238,8 @@ var li = new_play_item (GAME_NAME, CUR_PLAY_I); old_li.parentNode.replaceChild (li, old_li); if (PLAYS[CUR_PLAY_I][(m + 1) % 2] == "computer") { - suggest_move (); - make_move (); + var m = suggest_move (); + if (m != "") { make_move (); } } } @@ -345,12 +369,14 @@ function suggest_move () { var m = srv("SUGGEST", 'c, '+ play_py_id (CUR_PLAY_I)); - show_move (m); + if (m != "") { show_move (m); } + return (m); } function suggest_move_better () { var m = srv("SUGGESTX", 'c, '+ play_py_id (CUR_PLAY_I)); - show_move (m); + if (m != "") { show_move (m); } + return (m); } function toggle_suggestions () { Modified: trunk/Toss/WebClient/README =================================================================== --- trunk/Toss/WebClient/README 2010-12-21 23:14:48 UTC (rev 1268) +++ trunk/Toss/WebClient/README 2010-12-21 23:42:15 UTC (rev 1269) @@ -19,8 +19,6 @@ TODO: - - move interface: first click all, second click toggle, if one - confirm msg - - display results, prevent suggestion bug when game has already ended - sort plays by who's turn it is - option to give up game and offer a draw - enable google (or other) analytics Modified: trunk/Toss/WebClient/Style.css =================================================================== --- trunk/Toss/WebClient/Style.css 2010-12-21 23:14:48 UTC (rev 1268) +++ trunk/Toss/WebClient/Style.css 2010-12-21 23:42:15 UTC (rev 1269) @@ -2,14 +2,16 @@ html { position: absolute; - height: 100%; + min-height: 100%; + height: auto; + min-width: 45em; width: 100%; } body { position: absolute; - height: 100%; width: 100%; + min-height: 100%; padding: 0px; margin: 0px; text-align: center; @@ -23,7 +25,7 @@ -moz-border-radius: 4px; border-width: 1px; color: #260314; - background-color: #ffe4aa; + background-color: #fff1d4; font-size: 0.9em; font-family: Verdana, 'TeXGyreHerosRegular', sans; } @@ -34,10 +36,11 @@ } #plays .bt { - width: 7.5em; + width: 8em; font-size: 0.75em; - position: absolute; - right: 2px; + /* position: absolute; + right: 2px; */ + float: right; } .obt { @@ -47,7 +50,7 @@ -moz-border-radius: 4px; border-width: 0px; color: #260314; - background-color: #ffe4aa; + background-color: #fff1d4; font-size: 0.9em; font-family: Verdana, 'TeXGyreHerosRegular', sans; } @@ -58,11 +61,11 @@ } .dbt { - border-color: #ffe4aa; + border-color: #fff1d4; border-radius: 4px; -moz-border-radius: 4px; border-width: 0px; - color: #ffe4aa; + color: #fff1d4; background-color: #400827; font-size: 0.9em; font-family: Verdana, 'TeXGyreHerosRegular', sans; @@ -95,7 +98,7 @@ } .loginput { - border-color: #ffe4aa; + border-color: #fff1d4; border-radius: 4px; -moz-border-radius: 4px; border-width: 1px; @@ -104,7 +107,7 @@ } .forminput { - border-color: #ffe4aa; + border-color: #fff1d4; border-radius: 4px; -moz-border-radius: 4px; border-width: 2px; @@ -134,7 +137,7 @@ font-family: Verdana, 'TeXGyreHerosRegular', sans; color: #400827; background-color: #ffffff; - border-color: #ffe4aa; + border-color: #fff1d4; border-radius: 4px; -moz-border-radius: 4px; border-width: 1px; @@ -150,9 +153,9 @@ font-family: Verdana, 'TeXGyreHerosRegular', sans; font-size: 1em; font-weight: bold; - color: #ffe4aa; + color: #fff1d4; background-color: #400827; - border-color: #ffe4aa; + border-color: #fff1d4; border-radius: 4px; -moz-border-radius: 4px; border-width: 0px; @@ -189,7 +192,7 @@ } #top a, #logo a:link, #logo a:active, #logo a:visited { - color: #ffe4aa; + color: #fff1d4; background-color: transparent; text-decoration: none; } @@ -210,7 +213,7 @@ left: 0px; width: 100%; height: 2.5em; - color: #ffe4aa; + color: #fff1d4; background-color: #400827; border-color: #260314; border-style: solid; @@ -252,7 +255,7 @@ text-align: center; font-size: 0.9em; font-weight: bold; - color: #ffe4aa; + color: #fff1d4; background-color: #400827; border-color: #260314; border-style: solid; @@ -260,7 +263,7 @@ } #bottom a, #bottom a:link, #bottom a:active, #bottom a:visited { - color: #ffe4aa; + color: #fff1d4; text-decoration: none; } @@ -286,7 +289,7 @@ left: 0.5em; border: 0px; background-color: #400827; - color: #ffe4aa; + color: #fff1d4; font-family: Verdana, 'TeXGyreHerosRegular', sans; font-size: 1em; font-weight: bold; @@ -315,7 +318,7 @@ #topbar a { font-weight: bold; text-decoration: none; - color: #ffe4aa; + color: #fff1d4; width: 100%; } @@ -338,29 +341,28 @@ text-align: left; position: absolute; top: 0px; - bottom: 0px; left: 0px; right: 0px; margin-left: auto; margin-right: auto; width: 90%; - height: 100%; + min-height: 100%; padding-top: 0px; padding-bottom: 0px; padding-left: 2px; padding-right: 2px; color: #260314; - background-color: #ffe4aa; + background-color: #fff1d4; border-left: 1px solid #260314; border-right: 1px solid #260314; } -#main a, #main a:link, #main a:active, #main a:visited { +#welcome a, #welcome a:link, #welcome a:active, #welcome a:visited { color: #260314; text-decoration: none; } -#main a:hover { +#welcome a:hover { color: #400827; text-decoration: underline; } @@ -386,7 +388,7 @@ width: 20em; margin-left: auto; margin-right: auto; - color: #ffe4aa; + color: #fff1d4; background-color: #400827; font-weight: bold; padding: 1em; @@ -420,7 +422,7 @@ -moz-border-radius: 4px; border-width: 1px; color: #260314; - background-color: #ffe4aa; + background-color: #fff1d4; font-weight: normal; text-align: center; font-size: 0.9em; @@ -456,9 +458,10 @@ margin-left: auto; margin-right: auto; margin-top: 3em; + margin-bottom: 1.5em; min-width: 10em; - max-width: 90em; - width: 80%; + max-width: 120em; + width: 100%; display: none; } @@ -482,8 +485,8 @@ #board { min-width: 10em; - max-width: 90em; - width: 70%; + max-width: 120em; + width: 100%; margin-left: auto; margin-right: auto; margin-top: 0em; @@ -500,7 +503,7 @@ margin-right: auto; text-align: center; font-weight: bold; - color: #ffe4aa; + color: #fff1d4; background-color: #400827; display: none; padding: 1em; @@ -513,7 +516,7 @@ width: 16em; text-align: center; font-weight: bold; - color: #ffe4aa; + color: #fff1d4; background-color: #400827; display: none; padding: 1em; @@ -531,10 +534,12 @@ } #plays { - position: absolute; + /* position: absolute; left: 0px; right: 0px; - top: 2.5em; + top: 2.5em; */ + margin-top: 3.5em; + margin-bottom: 2em; margin-left: auto; margin-right: auto; width: 100%; @@ -542,6 +547,16 @@ display: none; } +#plays a, #plays a:link, #plays a:active, #plays a:visited { + color: #260314; + text-decoration: none; +} + +#plays a:hover { + color: #400827; + text-decoration: underline; +} + .plays-list { margin-left: 1em; padding-left: 0px; @@ -569,22 +584,34 @@ /* SVG styling */ #svg { min-width: 10em; - max-width: 90em; - width: 80%; + max-width: 120em; + width: 65%; min-height: 10em; - max-height: 90em; - height: 80%; + max-height: 120em; + height: 75%; /* border: 1px solid #260314; */ } -.model-elem { - fill: #b5bf8f; +.model-elem, .model-elem-0, .model-elem-1 { + fill: #ffe4aa; /* #ffce9e; */ stroke: #260314; stroke-width: 3px; } +.Game-Chess .model-elem-0 { + fill: #d18b47; + stroke: #260314; + stroke-width: 3px; +} + +.Game-Chess .model-elem-1 { + fill: #ffe4aa; /* #ffce9e; */ + stroke: #260314; + stroke-width: 3px; +} + .model-elem-highlight { - fill: #ffe4aa; + fill: #b5bf8f; stroke: #400827; stroke-width: 3px; } @@ -596,12 +623,12 @@ } .model-pred-Q { - fill: #b5bf8f; + fill: #ffe4aa; /* #ffce9e; */ stroke: #260314; } .model-pred-C { - fill: #ffe4aa; + fill: #fff1d4; stroke: #260314; stroke-width: 3px; } @@ -613,7 +640,7 @@ } .model-pred-W { - fill: #ffe4aa; + fill: #fff1d4; stroke: #260314; stroke-width: 3px; } @@ -632,7 +659,7 @@ .chessW .chess-path-A { opacity: 1; - fill: #ffe4aa; + fill: #fff1d4; fill-opacity: 1; fill-rule: nonzero; stroke: #260314; @@ -662,7 +689,7 @@ .chessW .chess-path-B { opacity: 1; - fill: #ffe4aa; + fill: #fff1d4; fill-opacity: 1; fill-rule: evenodd; stroke: #260314; @@ -690,7 +717,7 @@ .chessW .chess-path-Bx { opacity: 1; - fill: #ffe4aa; + fill: #fff1d4; fill-opacity: 1; fill-rule: evenodd; stroke: #260314; @@ -704,7 +731,7 @@ .chessB .chess-path-Bx { opacity: 1; - fill: #ffe4aa; + fill: #fff1d4; fill-opacity: 1; fill-rule: evenodd; stroke: #400827; @@ -731,9 +758,9 @@ .chessB .chess-path-C { opacity:1; - fill: #ffe4aa; + fill: #fff1d4; fill-opacity: 1; - stroke: #ffe4aa; + stroke: #fff1d4; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; @@ -743,7 +770,7 @@ } .chessW .chess-path-D { - fill: #ffe4aa; + fill: #fff1d4; fill-opacity: 0.75; fill-rule: evenodd; stroke: #260314; @@ -759,7 +786,7 @@ fill: #400827; fill-opacity: 0.75; fill-rule: evenodd; - stroke: #ffe4aa; + stroke: #fff1d4; stroke-width: 1; stroke-linecap: round; stroke-linejoin: miter; Modified: trunk/Toss/WebClient/Wrapper.py =================================================================== --- trunk/Toss/WebClient/Wrapper.py 2010-12-21 23:14:48 UTC (rev 1268) +++ trunk/Toss/WebClient/Wrapper.py 2010-12-21 23:42:15 UTC (rev 1269) @@ -221,6 +221,7 @@ " alpha_beta_ord") self.set_time (ts, t) msg = [s.strip() for s in m.split(';')] + if len(msg) < 2: return ("") emb = dict() for s in msg[1].split(','): es = [x.strip() for x in s.split(':')] Modified: trunk/Toss/WebClient/index.html =================================================================== --- trunk/Toss/WebClient/index.html 2010-12-21 23:14:48 UTC (rev 1268) +++ trunk/Toss/WebClient/index.html 2010-12-21 23:42:15 UTC (rev 1269) @@ -15,6 +15,9 @@ </head> <body onload="startup()"> + +<div id="main"> + <div id="top"> <div id="logo"><a href="index.html">tPlay</a></div> <div id="topbar"> @@ -49,9 +52,7 @@ <a href="register.html">Register</a> </span> </div> -</div> -<div id="main"> <div id="opponents"> Pick Opponent: @@ -150,7 +151,6 @@ <div id="board"><div id="working">Working...</div></div> </div> -</div> <div id="bottom"> <button id="suggestions-toggle" onclick="toggle_suggestions()"> @@ -160,5 +160,7 @@ <a href="contact.html" id="contact">Contact and Info</a> </div> +</div> + </body> </html> Modified: trunk/Toss/examples/Gomoku.toss =================================================================== --- trunk/Toss/examples/Gomoku.toss 2010-12-21 23:14:48 UTC (rev 1268) +++ trunk/Toss/examples/Gomoku.toss 2010-12-21 23:42:15 UTC (rev 1269) @@ -1,157 +1,45 @@ PLAYERS 1, 2 DATA r1: circle, r2: line, adv_ratio: 4, depth: 1 +REL DiagA (x, y) = ex u (R(x, u) and C(u, y)) +REL DiagB (x, y) = ex u (R(x, u) and C(y, u)) +REL Row5 (x, y, z, v, w) = R(x, y) and R(y, z) and R(z, v) and R(v, w) +REL Col5 (x, y, z, v, w) = C(x, y) and C(y, z) and C(z, v) and C(v, w) +REL DiagA5 (x, y, z, v, w) = + DiagA(x, y) and DiagA(y, z) and DiagA(z, v) and DiagA(v, w) +REL DiagB5 (x, y, z, v, w) = + DiagB(x, y) and DiagB(y, z) and DiagB(z, v) and DiagB(v, w) +REL Conn5 (x, y, z, v, w) = + Row5(x,y,z,v,w) or Col5(x,y,z,v,w) or DiagA5(x,y,z,v,w) or DiagB5(x,y,z,v,w) +REL WinQ() = + ex x,y,z,v,w (Q(x) and Q(y) and Q(z) and Q(v) and Q(w) and Conn5(x,y,z,v,w)) +REL WinP() = + ex x,y,z,v,w (P(x) and P(y) and P(z) and P(v) and P(w) and Conn5(x,y,z,v,w)) RULE Cross: - [a1 | P:1 {}; Q:1 {} | vx {a1->0.}; vy {a1->0.}; x {a1->0.}; y {a1->0.}] -> + [a1 | P:1 {}; Q:1 {} | vx {a1->0.}; vy {a1->0.}; x {a1->0.}; y {a1->0.}] + -> [a1 | P (a1); Q:1 {} | vx {a1->0.}; vy {a1->0.}; x {a1->0.}; y {a1->0.}] - emb Q, P - pre - not - ex v, w, x, y, z - (Q(v) and Q(w) and Q(x) and Q(y) and Q(z) and - (R(v, w) and R(w, x) and R(x, y) and R(y, z) or - C(v, w) and C(w, x) and C(x, y) and C(y, z) or - ex r, s, t, u - (R(v, r) and C(r, w) and R(w, s) and C(s, x) and R(x, t) and C(t, y) and - R(y, u) and - C(u, z)) or - ex r, s, t, u - (R(v, r) and C(w, r) and R(w, s) and C(x, s) and R(x, t) and C(y, t) and - R(y, u) and - C(z, u)))) + emb Q, P pre not WinQ() RULE Circle: - [a1 | P:1 {}; Q:1 {} | vx {a1->0.}; vy {a1->0.}; x {a1->0.}; y {a1->0.}] -> + [a1 | P:1 {}; Q:1 {} | vx {a1->0.}; vy {a1->0.}; x {a1->0.}; y {a1->0.}] + -> [a1 | P:1 {}; Q (a1) | vx {a1->0.}; vy {a1->0.}; x {a1->0.}; y {a1->0.}] - emb Q, P - pre - not - ex v, w, x, y, z - (P(v) and P(w) and P(x) and P(y) and P(z) and - (R(v, w) and R(w, x) and R(x, y) and R(y, z) or - C(v, w) and C(w, x) and C(x, y) and C(y, z) or - ex r, s, t, u - (R(v, r) and C(r, w) and R(w, s) and C(s, x) and R(x, t) and C(t, y) and - R(y, u) and - C(u, z)) or - ex r, s, t, u - (R(v, r) and C(w, r) and R(w, s) and C(x, s) and R(x, t) and C(y, t) and - R(y, u) and - C(z, u)))) + emb Q, P pre not WinP() LOC 0 { - PLAYER 1 + PLAYER 1 PAYOFF { - 1: - :( - ex v, w, x, y, z - (P(v) and P(w) and P(x) and P(y) and P(z) and - (C(v, w) and C(w, x) and C(x, y) and C(y, z) or - R(v, w) and R(w, x) and R(x, y) and R(y, z) or - ex r, s, t, u - (C(r, w) and C(s, x) and C(t, y) and C(u, z) and R(v, r) and R(w, - s) and R(x, t) and R(y, u)) or - ex r, s, t, u - (R(v, r) and C(w, r) and R(w, s) and C(x, s) and R(x, t) and C(y, - t) and R(y, u) and C(z, u)))) - ) + - -1. * - :( - ex v, w, x, y, z - (Q(v) and Q(w) and Q(x) and Q(y) and Q(z) and - (C(v, w) and C(w, x) and C(x, y) and C(y, z) or - R(v, w) and R(w, x) and R(x, y) and R(y, z) or - ex r, s, t, u - (C(r, w) and C(s, x) and C(t, y) and C(u, z) and R(v, r) and R(w, - s) and R(x, t) and R(y, u)) or - ex r, s, t, u - (R(v, r) and C(w, r) and R(w, s) and C(x, s) and R(x, t) and C(y, - t) and R(y, u) and C(z, u)))) - ); - 2: - :( - ex v, w, x, y, z - (Q(v) and Q(w) and Q(x) and Q(y) and Q(z) and - (C(v, w) and C(w, x) and C(x, y) and C(y, z) or - R(v, w) and R(w, x) and R(x, y) and R(y, z) or - ex r, s, t, u - (C(r, w) and C(s, x) and C(t, y) and C(u, z) and R(v, r) and R(w, - s) and R(x, t) and R(y, u)) or - ex r, s, t, u - (R(v, r) and C(w, r) and R(w, s) and C(x, s) and R(x, t) and C(y, - t) and R(y, u) and C(z, u)))) - ) + - -1. * - :( - ex v, w, x, y, z - (P(v) and P(w) and P(x) and P(y) and P(z) and - (C(v, w) and C(w, x) and C(x, y) and C(y, z) or - R(v, w) and R(w, x) and R(x, y) and R(y, z) or - ex r, s, t, u - (C(r, w) and C(s, x) and C(t, y) and C(u, z) and R(v, r) and R(w, - s) and R(x, t) and R(y, u)) or - ex r, s, t, u - (R(v, r) and C(w, r) and R(w, s) and C(x, s) and R(x, t) and C(y, - t) and R(y, u) and C(z, u)))) - ) - } + 1: :(WinP()) - :(WinQ()); + 2: :(WinQ()) - :(WinP()) + } MOVES [Cross -> 1] - } +} LOC 1 { - PLAYER 2 + PLAYER 2 PAYOFF { - 1: - :( - ex v, w, x, y, z - (P(v) and P(w) and P(x) and P(y) and P(z) and - (C(v, w) and C(w, x) and C(x, y) and C(y, z) or - R(v, w) and R(w, x) and R(x, y) and R(y, z) or - ex r, s, t, u - (C(r, w) and C(s, x) and C(t, y) and C(u, z) and R(v, r) and R(w, - s) and R(x, t) and R(y, u)) or - ex r, s, t, u - (R(v, r) and C(w, r) and R(w, s) and C(x, s) and R(x, t) and C(y, - t) and R(y, u) and C(z, u)))) - ) + - -1. * - :( - ex v, w, x, y, z - (Q(v) and Q(w) and Q(x) and Q(y) and Q(z) and - (C(v, w) and C(w, x) and C(x, y) and C(y, z) or - R(v, w) and R(w, x) and R(x, y) and R(y, z) or - ex r, s, t, u - (C(r, w) and C(s, x) and C(t, y) and C(u, z) and R(v, r) and R(w, - s) and R(x, t) and R(y, u)) or - ex r, s, t, u - (R(v, r) and C(w, r) and R(w, s) and C(x, s) and R(x, t) and C(y, - t) and R(y, u) and C(z, u)))) - ); - 2: - :( - ex v, w, x, y, z - (Q(v) and Q(w) and Q(x) and Q(y) and Q(z) and - (C(v, w) and C(w, x) and C(x, y) and C(y, z) or - R(v, w) and R(w, x) and R(x, y) and R(y, z) or - ex r, s, t, u - (C(r, w) and C(s, x) and C(t, y) and C(u, z) and R(v, r) and R(w, - s) and R(x, t) and R(y, u)) or - ex r, s, t, u - (R(v, r) and C(w, r) and R(w, s) and C(x, s) and R(x, t) and C(y, - t) and R(y, u) and C(z, u)))) - ) + - -1. * - :( - ex v, w, x, y, z - (P(v) and P(w) and P(x) and P(y) and P(z) and - (C(v, w) and C(w, x) and C(x, y) and C(y, z) or - R(v, w) and R(w, x) and R(x, y) and R(y, z) or - ex r, s, t, u - (C(r, w) and C(s, x) and C(t, y) and C(u, z) and R(v, r) and R(w, - s) and R(x, t) and R(y, u)) or - ex r, s, t, u - (R(v, r) and C(w, r) and R(w, s) and C(x, s) and R(x, t) and C(y, - t) and R(y, u) and C(z, u)))) - ) - } + 1: :(WinP()) - :(WinQ()); + 2: :(WinQ()) - :(WinP()) + } MOVES [Circle -> 0] - } +} MODEL [ | P:1 {}; Q:1 {} | ] " ... ... ... ... Modified: trunk/Toss/examples/Tic-Tac-Toe.toss =================================================================== --- trunk/Toss/examples/Tic-Tac-Toe.toss 2010-12-21 23:14:48 UTC (rev 1268) +++ trunk/Toss/examples/Tic-Tac-Toe.toss 2010-12-21 23:42:15 UTC (rev 1269) @@ -1,43 +1,41 @@ PLAYERS 1, 2 DATA r1: circle, r2: line, adv_ratio: 4, depth: 3 -REL WinQ() = - ex x, y, z - (Q(x) and Q(y) and Q(z) and ( - (R(x, y) and R(y, z)) or - (C(x, y) and C(y, z)) or - (ex u, v (R(x, v) and C(v, y) and R(y, u) and C(u, z))) or - (ex u, v (R(x, v) and C(y, v) and R(y, u) and C(z, u))) )) -REL WinP() = - ex x, y, z - (P(x) and P(y) and P(z) and ( - (R(x, y) and R(y, z)) or - (C(x, y) and C(y, z)) or - (ex u, v (R(x, v) and C(v, y) and R(y, u) and C(u, z))) or - (ex u, v (R(x, v) and C(y, v) and R(y, u) and C(z, u))) )) +REL DiagA (x, y) = ex u (R(x, u) and C(u, y)) +REL DiagB (x, y) = ex u (R(x, u) and C(y, u)) +REL Row3 (x, y, z) = R(x, y) and R(y, z) +REL Col3 (x, y, z) = C(x, y) and C(y, z) +REL DiagA3 (x, y, z) = DiagA(x, y) and DiagA(y, z) +REL DiagB3 (x, y, z) = DiagB(x, y) and DiagB(y, z) +REL Conn3 (x, y, z) = + Row3(x, y, z) or Col3(x, y, z) or DiagA3(x, y, z) or DiagB3(x, y, z) +REL WinQ() = ex x, y, z (Q(x) and Q(y) and Q(z) and Conn3(x, y, z)) +REL WinP() = ex x, y, z (P(x) and P(y) and P(z) and Conn3(x, y, z)) RULE Cross: - [a1 | P:1 {}; Q:1 {} | vx {a1->0.}; vy {a1->0.}; x {a1->0.}; y {a1->0.}] -> + [a1 | P:1 {}; Q:1 {} | vx {a1->0.}; vy {a1->0.}; x {a1->0.}; y {a1->0.}] + -> [a1 | P (a1); Q:1 {} | vx {a1->0.}; vy {a1->0.}; x {a1->0.}; y {a1->0.}] - emb Q, P pre not WinQ() + emb Q, P pre not WinQ() RULE Circle: - [a1 | P:1 {}; Q:1 {} | vx {a1->0.}; vy {a1->0.}; x {a1->0.}; y {a1->0.}] -> + [a1 | P:1 {}; Q:1 {} | vx {a1->0.}; vy {a1->0.}; x {a1->0.}; y {a1->0.}] + -> [a1 | P:1 {}; Q (a1) | vx {a1->0.}; vy {a1->0.}; x {a1->0.}; y {a1->0.}] - emb Q, P pre not WinP() + emb Q, P pre not WinP() LOC 0 { - PLAYER 1 + PLAYER 1 PAYOFF { 1: :(WinP()) - :(WinQ()); 2: :(WinQ()) - :(WinP()) - } + } MOVES [Cross -> 1] - } +} LOC 1 { - PLAYER 2 + PLAYER 2 PAYOFF { 1: :(WinP()) - :(WinQ()); 2: :(WinQ()) - :(WinP()) - } + } MOVES [Circle -> 0] - } +} MODEL [ | P:1 {}; Q:1 {} | ] " This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-21 23:14:54
|
Revision: 1268 http://toss.svn.sourceforge.net/toss/?rev=1268&view=rev Author: lukstafi Date: 2010-12-21 23:14:48 +0000 (Tue, 21 Dec 2010) Log Message: ----------- GDL breakthrough (tentative hardcoded) Modified Paths: -------------- trunk/Toss/Play/GDL.ml Modified: trunk/Toss/Play/GDL.ml =================================================================== --- trunk/Toss/Play/GDL.ml 2010-12-21 16:11:28 UTC (rev 1267) +++ trunk/Toss/Play/GDL.ml 2010-12-21 23:14:48 UTC (rev 1268) @@ -51,7 +51,7 @@ Printf.printf "GDL: File %s loaded.\n%!" s; res -let initialize_game state player game_descr startcl = +let initialize_game_gomoku state player game_descr startcl = state := state_of_file "./examples/Gomoku.toss"; playing_as := player; game_description := game_descr; @@ -59,8 +59,20 @@ let effort, horizon, heur_adv_ratio = 2, 100, 4.0 in effort, horizon, heur_adv_ratio + +let initialize_game_breakthrough state player game_descr startcl = + state := state_of_file "./examples/Breakthrough.toss"; + playing_as := player; + game_description := game_descr; + player_name_terms := [|Const "WHITE"; Const "BLACK"|]; + let effort, horizon, heur_adv_ratio = + 2, 100, 2.0 in + effort, horizon, heur_adv_ratio + +let initialize_game = + initialize_game_breakthrough -let translate_last_action actions = +let translate_last_action_gomoku actions = let number_of_letter c = string_of_int ((Char.code (Char.lowercase c)) - 96) in match actions with @@ -72,17 +84,65 @@ | [ Const "NOOP"; Func ("MARK", [Const col; Const row])] -> "Circle", ["a1", ((String.lowercase col) ^ (number_of_letter row.[0]))] | _ -> assert false + +let s2i = int_of_string +let translate_last_action_breakthrough actions = + match actions with + | [] -> + (* start of game -- Server will handle this answer as NOOP *) + "", [] + | [Func ("MOVE", [Const x1; Const y1; Const x2; Const y2]); + Const "NOOP"] when x1 = x2 -> + "WhiteStraight", + ["a1", Structure.board_coords_name (s2i x1, s2i y1); + "a2", Structure.board_coords_name (s2i x2, s2i y2)] + | [Func ("MOVE", [Const x1; Const y1; Const x2; Const y2]); + Const "NOOP"] -> + "WhiteDiag", + ["a", Structure.board_coords_name (s2i x1, s2i y1); + "b", Structure.board_coords_name (s2i x2, s2i y2)] + | [Const "NOOP"; + Func ("MOVE", [Const x1; Const y1; Const x2; Const y2])] + when x1 = x2 -> + "BlackStraight", + ["a2", Structure.board_coords_name (s2i x1, s2i y1); + "a1", Structure.board_coords_name (s2i x2, s2i y2)] + | [Const "NOOP"; + Func ("MOVE", [Const x1; Const y1; Const x2; Const y2])] -> + "BlackDiag", + ["a", Structure.board_coords_name (s2i x1, s2i y1); + "b", Structure.board_coords_name (s2i x2, s2i y2)] + | _ -> assert false + +let translate_last_action = + translate_last_action_breakthrough + let our_turn state = let loc = state.Arena.cur_loc in let loc_player = state.Arena.game.Arena.graph.(loc).Arena.player in !player_name_terms.(loc_player) = !playing_as -let translate_move rule emb new_state = +let translate_move_gomoku rule emb new_state = let struc = new_state.Arena.struc in let elem = snd (List.hd emb) in let c, r = Structure.board_elem_coords (Structure.elem_str struc elem) in let cs, rs = Char.chr (c + 64), Char.chr (r + 64) in Printf.sprintf "(MARK %c %c)" cs rs + +let translate_move_breakthrough rule emb new_state = + let struc = new_state.Arena.struc in + match emb with + | [(_,a); (_,b)] -> + let a, b = if rule = "BlackStraight" then b, a else a, b in + let x1, y1 = + Structure.board_elem_coords (Structure.elem_str struc a) + and x2, y2 = + Structure.board_elem_coords (Structure.elem_str struc b) in + Printf.sprintf "(MOVE %d %d %d %d)" x1 y1 x2 y2 + | _ -> assert false + +let translate_move = + translate_move_breakthrough This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-21 16:11:35
|
Revision: 1267 http://toss.svn.sourceforge.net/toss/?rev=1267&view=rev Author: lukstafi Date: 2010-12-21 16:11:28 +0000 (Tue, 21 Dec 2010) Log Message: ----------- Zero effort handling. Recomputation on timeout fix. Better time logging. Modified Paths: -------------- trunk/Toss/Play/GDL.ml trunk/Toss/Play/GDL.mli trunk/Toss/Play/GDLParser.mly trunk/Toss/Play/Game.ml trunk/Toss/Play/Game.mli trunk/Toss/Play/GameTest.ml trunk/Toss/Play/KIFLexer.mll trunk/Toss/Play/Server.ml Modified: trunk/Toss/Play/GDL.ml =================================================================== --- trunk/Toss/Play/GDL.ml 2010-12-21 00:18:56 UTC (rev 1266) +++ trunk/Toss/Play/GDL.ml 2010-12-21 16:11:28 UTC (rev 1267) @@ -28,12 +28,8 @@ | Atomic of string * term list -(* Pbbly will change to a compiled form. *) -type game_description = - game_descr_entry list - type request = - | Start of string * term * game_description * int * int + | Start of string * term * game_descr_entry list * int * int (* prepare game: match id, role, game, startclock, playclock *) | Play of string * term list (* request a move: match id, actions on previous step *) Modified: trunk/Toss/Play/GDL.mli =================================================================== --- trunk/Toss/Play/GDL.mli 2010-12-21 00:18:56 UTC (rev 1266) +++ trunk/Toss/Play/GDL.mli 2010-12-21 16:11:28 UTC (rev 1267) @@ -27,21 +27,17 @@ | Initial of term * literal list | Atomic of string * term list -type game_description - type request = - | Start of string * term * game_description * int * int + | Start of string * term * game_descr_entry list * int * int (** prepare game: match id, role, game, startclock, playclock *) | Play of string * term list (** request a move: match id, actions on previous step *) | Stop of string * term list (** game ends here: match id, actions on previous step *) -val compile_game_descr : - game_descr_entry list -> game_description - val initialize_game : - Arena.game_state ref -> term -> game_description -> int -> int * int * float + Arena.game_state ref -> term -> game_descr_entry list -> int -> + int * int * float val translate_last_action : term list -> string * (string * string) list Modified: trunk/Toss/Play/GDLParser.mly =================================================================== --- trunk/Toss/Play/GDLParser.mly 2010-12-21 00:18:56 UTC (rev 1266) +++ trunk/Toss/Play/GDLParser.mly 2010-12-21 16:11:28 UTC (rev 1267) @@ -7,7 +7,7 @@ %token <string> WORD %token <string> INDVAR %token <string> SEQVAR -%token OPEN CLOSE COMMA QUOTE SEMICOLON BACKQUOTE DBLQUOTE SHARP DOT +%token OPEN CLOSE COMMA QUOTE BACKQUOTE DBLQUOTE SHARP DOT %token NOT_EQ NOT AND OR IMPL REVIMPL EQUIV LISTOF SETOF QUOTE_KWD %token IF COND THE SETOFALL KAPPA LAMBDA RULE_RIGHT RULE_LEFT CONSIS %token DEFOBJECT DEFUNCTION DEFRELATION ASSIGN ASSIGN_IMPLIES ASSIGN_AND @@ -16,7 +16,7 @@ %start parse_game_description parse_request %type <GDL.request> parse_request request -%type <GDL.game_description> parse_game_description game_description +%type <GDL.game_descr_entry list> parse_game_description game_description %% @@ -101,7 +101,7 @@ %public game_description: | OPEN descr=list(game_descr_entry) CLOSE - { compile_game_descr descr } + { descr } | error { Lexer.report_parsing_error $startpos $endpos "GDL: Syntax error in game description." } Modified: trunk/Toss/Play/Game.ml =================================================================== --- trunk/Toss/Play/Game.ml 2010-12-21 00:18:56 UTC (rev 1266) +++ trunk/Toss/Play/Game.ml 2010-12-21 16:11:28 UTC (rev 1267) @@ -16,7 +16,17 @@ let timeout = ref false let get_timeout () = !timeout let cancel_timeout () = - ignore (Unix.alarm 0); timeout := false + let remaining = Unix.alarm 0 in + (* {{{ log entry *) + if !debug_level > 0 then ( + if !timeout then + Printf.printf "Computation finished during timeout.\n%!" + else + Printf.printf "Computation finished with %d seconds left.\n%!" + remaining + ); + (* }}} *) + timeout := false let trigger_timeout _ = (* if !debug_level > 0 then printf " TIMEOUT %!"; *) @@ -168,13 +178,13 @@ | Random_move (* select a random move; avoids rewriting all matches and calling evaluation games *) - | Maximax_evgame of evaluation_game * bool * int * bool * bool + | Maximax_evgame of evaluation_game * bool * int * bool (* select a move according to evaluation games played in each leaf state; in a cooperative/competitive way (see {!uct_params}); expand the full game subtree to the given depth and propagate evaluation game results from leaves by taking cooperative/competitive best move for location's - player; optional alpha-beta-like pruning; optional move + player; optional alpha-beta-like pruning, with move reordering based on afterstate heuristic value *) | Tree_search of evaluation_game * int option * uct_params * agent array (* Monte-Carlo tree search; uses the evaluation game to compute @@ -648,7 +658,9 @@ ended. Return the move chosen and the moves considered. One can use only a {!move} to suggest a move, or only the updated {!play_state} to follow the best move (or both). Also return the accrued - computation as updated "memory" for the current state. *) + computation as updated "memory" for the current state. + + Use [Random_move] for other agents if their "effort" is set to zero. *) and toss ~grid_size ?(just_payoffs=false) ({game={Arena.rules=rules; graph=graph; num_players=num_players; defined_rels=defined_rels}; @@ -669,7 +681,10 @@ else let agent = agents.(loc.Arena.player) in match agent with - | Random_move -> + + | Random_move + | Maximax_evgame (_, _, 0, _) + | Tree_search (_, _, {iters=0}, _) -> let mlen = Array.length moves in let init_pos = Random.int mlen in let pos = ref init_pos in @@ -700,7 +715,7 @@ {game_state = state; memory = update_memory ~num_players state !pos memory})) - | Maximax_evgame (subgames, cooperative, depth, use_pruning, reorder) -> + | Maximax_evgame (subgames, cooperative, depth, use_pruning) -> (* {{{ log entry *) let nodes_count = ref 0 in let size_count = ref 1 in @@ -709,14 +724,13 @@ if !debug_level > 1 && depth > 1 || !debug_level > 3 then ( printf "toss: %s%s ev game, timer started...\n%!" - (if use_pruning then "alpha_beta" else "maximax") - (if reorder then "_ord" else ""); + (if use_pruning then "alpha_beta_ord" else "maximax"); debug_playclock := Sys.time ()); (* }}} *) (* full tree search of limited depth by plain recursive calls, with optional alpha-beta pruning *) (* [betas] are used imperatively *) - let rec maximax_tree prev_player betas depth + let rec maximax_tree pre_heur prev_player betas depth {loc=loc; struc=model; time=time} = (* {{{ log entry *) incr nodes_count; @@ -733,7 +747,10 @@ (* }}} *) if depth < 1 || !timeout then ( (* leaf position *) let res = - play_evgame grid_size model time subgames.(loc) in + match pre_heur with + | Some h -> h + | None -> + play_evgame grid_size model time subgames.(loc) in (* {{{ log entry *) if !debug_level > 4 then ( let player = graph.(loc).Arena.player in @@ -769,25 +786,29 @@ let new_betas = Array.make num_players infinity in let index = Array.init (Array.length models) (fun i->i) in - if reorder && depth > 1 then begin - let heuristics = - gen_scores grid_size subgames moves models location in - Array.sort (fun j i-> compare - heuristics.(i).(player) heuristics.(j).(player)) index; - (* {{{ log entry *) - if !debug_level > 2 && (depth0 > 2 || !debug_level > 4) && - (depth > 1 || !debug_level > 3) - then - printf ", best %d pre-heur: %F %!" player - heuristics.(index.(0)).(player); - (* }}} *) - end; + let heuristics = + if depth > 1 then begin + let heuristics = + gen_scores grid_size subgames moves models location in + Array.sort (fun j i-> compare + heuristics.(i).(player) heuristics.(j).(player)) index; + (* {{{ log entry *) + if !debug_level > 2 && (depth0 > 2 || !debug_level > 4) && + (depth > 1 || !debug_level > 3) + then + printf ", best %d pre-heur: %F %!" player + heuristics.(index.(0)).(player); + (* }}} *) + Some heuristics + end else None in let rec aux best i = if i < n && not !timeout then let pos = index.(i) in let state = models.(pos) in let sub_heur = - maximax_tree player new_betas (depth-1) state in + maximax_tree + (Aux.map_option (fun h->h.(pos)) heuristics) + player new_betas (depth-1) state in (* note strong inequality: don't lose ordering info *) if now_pruning && sub_heur.(player) > betas.(player) then ( @@ -827,7 +848,7 @@ Aux.Right payoff else let scores = - Array.map (maximax_tree player betas (depth-1)) models in + Array.map (maximax_tree None player betas (depth-1)) models in let _, best = find_best_score ~use_det_setting:true cooperative player scores (Array.map (fun _ -> 1) scores) in @@ -1173,7 +1194,7 @@ if not (random_playout || heur_effect = Heuristic_only) then Array.map (fun _ -> Maximax_evgame - (heur_evgame, false, playout_mm_depth, true, false)) + (heur_evgame, false, playout_mm_depth, true)) game.Arena.graph else Array.map (fun _ -> Random_move) game.Arena.graph in Tree_search @@ -1184,8 +1205,7 @@ (* Plain limited depth maximax tree search. *) let default_maximax struc ~depth ?heuristic - ?(heur_adv_ratio=default_adv_ratio) ?(pruning=true) - ?(reorder=false) game = + ?(heur_adv_ratio=default_adv_ratio) ?(pruning=true) game = let heuristics = match heuristic with Some h -> h | None -> default_heuristic ~struc heur_adv_ratio game in @@ -1193,7 +1213,7 @@ Array.map (Array.map Solver.M.register_real_expr) heuristics in let heur_evgame = evgame_of_heuristic heuristics heuristics_pp game in - Maximax_evgame (heur_evgame, false, depth, pruning, reorder) + Maximax_evgame (heur_evgame, false, depth, pruning) (* An UCT-based agent that uses UCT-based playouts. *) let nested_treesearch struc iters reciters ?heuristic ?(random_playout=false) @@ -1229,13 +1249,10 @@ match search_method with | "maximax" -> default_maximax state.Arena.struc ~depth:effort ?heuristic - ?heur_adv_ratio ~pruning:false ~reorder:false game - | "alpha_beta" -> - default_maximax state.Arena.struc ~depth:effort ?heuristic - ?heur_adv_ratio ~pruning:true ~reorder:false game + ?heur_adv_ratio ~pruning:false game | "alpha_beta_ord" -> default_maximax state.Arena.struc ~depth:effort ?heuristic - ?heur_adv_ratio ~pruning:true ~reorder:true game + ?heur_adv_ratio ~pruning:true game | "uct_random_playouts" -> default_treesearch state.Arena.struc ~iters:effort ?heuristic ?heur_adv_ratio ?horizon @@ -1274,10 +1291,9 @@ subgames, sth, {params with iters=effort}, agents) | Maximax_evgame ( - subgames, cooperative, depth, use_pruning, reorder) -> + subgames, cooperative, depth, use_pruning) -> Maximax_evgame - (subgames, cooperative, effort, use_pruning, - reorder) + (subgames, cooperative, effort, use_pruning) | (Random_move | External _) as agent -> agent ) play.agents} in (* {{{ log entry *) Modified: trunk/Toss/Play/Game.mli =================================================================== --- trunk/Toss/Play/Game.mli 2010-12-21 00:18:56 UTC (rev 1266) +++ trunk/Toss/Play/Game.mli 2010-12-21 16:11:28 UTC (rev 1267) @@ -70,13 +70,13 @@ | Random_move (** select a random move; avoids rewriting all matches and calling evaluation games *) - | Maximax_evgame of evaluation_game * bool * int * bool * bool + | Maximax_evgame of evaluation_game * bool * int * bool (** select a move according to evaluation games played in each leaf state; in a cooperative/competitive way (see {!uct_params}); expand the full game subtree to the given depth and propagate evaluation game results from leaves by taking cooperative/competitive best move for location's player; optional - alpha-beta-like pruning; optional move reordering based on + alpha-beta-like pruning with move reordering based on afterstate heuristic value *) | Tree_search of evaluation_game * int option * uct_params * agent array (** Monte-Carlo tree search; uses the evaluation game to compute @@ -144,7 +144,7 @@ (** Plain limited depth maximax tree search. *) val default_maximax : Structure.structure -> depth:int -> ?heuristic:Formula.real_expr array array -> - ?heur_adv_ratio:float -> ?pruning:bool -> ?reorder:bool -> + ?heur_adv_ratio:float -> ?pruning:bool -> Arena.game -> agent Modified: trunk/Toss/Play/GameTest.ml =================================================================== --- trunk/Toss/Play/GameTest.ml 2010-12-21 00:18:56 UTC (rev 1266) +++ trunk/Toss/Play/GameTest.ml 2010-12-21 16:11:28 UTC (rev 1267) @@ -1172,10 +1172,10 @@ [| Game.default_maximax state.Arena.struc ~depth:1 ~heuristic:chess_piece_value_heur ~heur_adv_ratio - ~pruning:true ~reorder:true game; + ~pruning:true game; Game.default_maximax state.Arena.struc ~depth:2 ~heuristic:chess_piece_value_heur ~heur_adv_ratio - ~pruning:true ~reorder:true game; + ~pruning:true game; |]; delta = 2.0} in (* FIXME: give/calc delta *) let init_state = Game.initial_state play struc in @@ -1208,7 +1208,7 @@ let a () = run_test_tt ~verbose:true experiments let a () = - Server.set_debug_level 3 + Server.set_debug_level 1 let a () = match test_filter Modified: trunk/Toss/Play/KIFLexer.mll =================================================================== --- trunk/Toss/Play/KIFLexer.mll 2010-12-21 00:18:56 UTC (rev 1266) +++ trunk/Toss/Play/KIFLexer.mll 2010-12-21 16:11:28 UTC (rev 1267) @@ -7,7 +7,6 @@ | CLOSE | COMMA | QUOTE - | SEMICOLON | BACKQUOTE | DBLQUOTE | SHARP @@ -100,7 +99,6 @@ | ')' { CLOSE } | ',' { COMMA } | '\'' { QUOTE } - | ';' { SEMICOLON } | '`' { BACKQUOTE } | '"' { DBLQUOTE } | '#' { SHARP } @@ -148,4 +146,5 @@ ['!' '$' '%' '&' '*' '+' '-' '.' '/' '0'-'9' ':' '<' '>' '?' '@' 'A'-'Z' '[' ']' '^' '_' 'a'-'z' '{' '|' '}' '~']+ as s {SEQVAR s} + | ';' [^ '\n']* '\n' { incr_lineno lexbuf; lex lexbuf } | eof { EOF } Modified: trunk/Toss/Play/Server.ml =================================================================== --- trunk/Toss/Play/Server.ml 2010-12-21 00:18:56 UTC (rev 1266) +++ trunk/Toss/Play/Server.ml 2010-12-21 16:11:28 UTC (rev 1267) @@ -85,7 +85,9 @@ let http_beg_l = String.length http_beg in if line_in_len > http_beg_l && String.sub line_in 0 http_beg_l = http_beg then - "GDL " ^ Aux.input_http_message in_ch + let msg = Aux.input_http_message in_ch in + if !debug_level > 0 then Printf.printf "Rcvd: %s\n%!" msg; + "GDL " ^ msg else (* We put endlines, encoded by '$', back into the message. TODO: perhaps a "better" solution now that HTTP has one? *) @@ -148,6 +150,7 @@ let req_handle in_ch out_ch = try + let time_started = Sys.time () in let line = read_in_line in_ch in let req = req_of_str line in let resp = @@ -279,7 +282,6 @@ | Aux.Right (GDL.Play (_, actions)) -> - let time_started = int_of_float (Sys.time ()) in let r_name, mtch = GDL.translate_last_action actions in @@ -355,7 +357,7 @@ if GDL.our_turn !state then let time_used = - time_started - (int_of_float (ceil (Sys.time ()))) in + int_of_float time_started - int_of_float (ceil (Sys.time ())) in let p, ps = match !play, !play_state with | Some play, Some play_state -> @@ -380,7 +382,6 @@ | Aux.Right (GDL.Stop (_, actions)) -> - let time_started = int_of_float (Sys.time ()) in let r_name, mtch = GDL.translate_last_action actions in @@ -457,7 +458,10 @@ ^ "\r\n\r\nDONE" in - if !debug_level > 0 then print_endline ("Repl: " ^ resp ^ "\n"); + if !debug_level > 0 then ( + Printf.printf "Resp-time: %F\n%!" (Sys.time () -. time_started); + print_endline ("Repl: " ^ resp ^ "\n"); + ); output_string out_ch (resp ^ "\n"); flush out_ch; with This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-21 00:19:02
|
Revision: 1266 http://toss.svn.sourceforge.net/toss/?rev=1266&view=rev Author: lukaszkaiser Date: 2010-12-21 00:18:56 +0000 (Tue, 21 Dec 2010) Log Message: ----------- Corrections for Gomoku play and WebClient style. Modified Paths: -------------- trunk/Toss/Formula/FormulaOps.ml trunk/Toss/Play/GDL.ml trunk/Toss/Play/Server.ml trunk/Toss/WebClient/Style.css Modified: trunk/Toss/Formula/FormulaOps.ml =================================================================== --- trunk/Toss/Formula/FormulaOps.ml 2010-12-20 02:05:24 UTC (rev 1265) +++ trunk/Toss/Formula/FormulaOps.ml 2010-12-21 00:18:56 UTC (rev 1266) @@ -813,7 +813,9 @@ and append_quant vs ~universal flist = let (have_v, no_v) = List.partition (has_free vs) flist in - let res lst = if universal then Or lst else And lst in + let res = function + | [x] -> x + | lst -> if universal then Or lst else And lst in match have_v with [] -> res no_v | [phi] -> @@ -893,7 +895,31 @@ | Ex (vs, phi) -> Ex (vs, order_by_fv_phi acc_fv phi) | All (vs, phi) -> All (vs, order_by_fv_phi acc_fv phi) | f -> f - + +let rec push_in_quant phi = + match phi with + | In _ | Rel _ | Eq _ | RealExpr _ -> phi + | Not (Or fl) -> push_in_quant (And (List.map (fun f -> Not f) fl)) + | Not (And fl) -> push_in_quant (Or (List.map (fun f -> Not f) fl)) + | Not f -> Not (push_in_quant f) + | And fl -> And (List.map push_in_quant fl) + | Or fl -> Or (List.map push_in_quant fl) + | Ex ([], phi) | All ([], phi) -> push_in_quant phi + | Ex (vs, Or fl) -> push_in_quant (Or (List.map (fun f -> Ex (vs, f)) fl)) + | All (vs, And fl) -> push_in_quant (And(List.map (fun f -> All(vs,f)) fl)) + | Ex ([v], And fl) -> + append_quant [v] ~universal:false (List.map push_in_quant fl) + | Ex (vs, And fl) -> + push_in_quant (Ex ([List.hd vs], push_in_quant (Ex (List.tl vs, And fl)))) + | All ([v], Or fl) -> + append_quant [v] ~universal:true (List.map push_in_quant fl) + | All (vs, Or fl) -> + push_in_quant (All ([List.hd vs], push_in_quant (All (List.tl vs,Or fl)))) + | Ex (vs, f) -> Ex (vs, push_in_quant f) + | All (vs, f) -> All (vs, push_in_quant f) + +let rec push_quant f = push_in_quant (flatten_sort (f)) + let tnf_fv phi = let fv = free_vars phi in let psi = rename_quant_avoiding [] (Ex (fv, phi)) in Modified: trunk/Toss/Play/GDL.ml =================================================================== --- trunk/Toss/Play/GDL.ml 2010-12-20 02:05:24 UTC (rev 1265) +++ trunk/Toss/Play/GDL.ml 2010-12-21 00:18:56 UTC (rev 1266) @@ -56,27 +56,25 @@ res let initialize_game state player game_descr startcl = - state := state_of_file "./examples/Tic-Tac-Toe.toss"; + state := state_of_file "./examples/Gomoku.toss"; playing_as := player; game_description := game_descr; - player_name_terms := [|Const "XPLAYER"; Const "OPLAYER"|]; + player_name_terms := [|Const "X"; Const "O"|]; let effort, horizon, heur_adv_ratio = 2, 100, 4.0 in effort, horizon, heur_adv_ratio let translate_last_action actions = + let number_of_letter c = + string_of_int ((Char.code (Char.lowercase c)) - 96) in match actions with | [] -> (* start of game -- Server will handle this answer as NOOP *) "", [] | [Func ("MARK", [Const col; Const row]); Const "NOOP"] -> - "Cross", ["a1", - Structure.board_coords_name - (int_of_string col, int_of_string row)] + "Cross", ["a1", ((String.lowercase col) ^ (number_of_letter row.[0]))] | [ Const "NOOP"; Func ("MARK", [Const col; Const row])] -> - "Circle", ["a1", - Structure.board_coords_name - (int_of_string col, int_of_string row)] + "Circle", ["a1", ((String.lowercase col) ^ (number_of_letter row.[0]))] | _ -> assert false let our_turn state = @@ -90,4 +88,5 @@ let elem = snd (List.hd emb) in let c, r = Structure.board_elem_coords (Structure.elem_str struc elem) in - Printf.sprintf "(MARK %d %d)" c r + let cs, rs = Char.chr (c + 64), Char.chr (r + 64) in + Printf.sprintf "(MARK %c %c)" cs rs Modified: trunk/Toss/Play/Server.ml =================================================================== --- trunk/Toss/Play/Server.ml 2010-12-20 02:05:24 UTC (rev 1265) +++ trunk/Toss/Play/Server.ml 2010-12-21 00:18:56 UTC (rev 1266) @@ -361,7 +361,7 @@ | Some play, Some play_state -> play, play_state | _ -> assert false in - ignore (Unix.alarm (!playclock - time_used)); + ignore (Unix.alarm (!playclock - time_used - 1)); let res = Game.suggest p ps in Game.cancel_timeout (); let mov_msg = Modified: trunk/Toss/WebClient/Style.css =================================================================== --- trunk/Toss/WebClient/Style.css 2010-12-20 02:05:24 UTC (rev 1265) +++ trunk/Toss/WebClient/Style.css 2010-12-21 00:18:56 UTC (rev 1266) @@ -34,7 +34,7 @@ } #plays .bt { - width: 7em; + width: 7.5em; font-size: 0.75em; position: absolute; right: 2px; @@ -457,7 +457,7 @@ margin-right: auto; margin-top: 3em; min-width: 10em; - max-width: 60em; + max-width: 90em; width: 80%; display: none; } @@ -482,7 +482,7 @@ #board { min-width: 10em; - max-width: 60em; + max-width: 90em; width: 70%; margin-left: auto; margin-right: auto; @@ -569,11 +569,11 @@ /* SVG styling */ #svg { min-width: 10em; - max-width: 60em; - width: 70%; + max-width: 90em; + width: 80%; min-height: 10em; - max-height: 60em; - height: 70%; + max-height: 90em; + height: 80%; /* border: 1px solid #260314; */ } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-20 02:05:30
|
Revision: 1265 http://toss.svn.sourceforge.net/toss/?rev=1265&view=rev Author: lukaszkaiser Date: 2010-12-20 02:05:24 +0000 (Mon, 20 Dec 2010) Log Message: ----------- Corrections to play Tic-Tac-Toe on GGP server. (Test broken just this one time.) Modified Paths: -------------- trunk/Toss/Formula/Aux.ml trunk/Toss/Formula/Aux.mli trunk/Toss/Play/GDL.ml Modified: trunk/Toss/Formula/Aux.ml =================================================================== --- trunk/Toss/Formula/Aux.ml 2010-12-20 00:14:59 UTC (rev 1264) +++ trunk/Toss/Formula/Aux.ml 2010-12-20 02:05:24 UTC (rev 1265) @@ -398,16 +398,26 @@ with End_of_file -> ()); Buffer.contents buf +let is_space c = + c = '\n' || c = '\r' || c = ' ' || c = '\t' + +let strip_spaces s = + let (b, e) = (ref 0, ref ((String.length s) - 1)) in + while !b < !e && is_space (s.[!b]) do b := !b + 1 done; + while !b <= !e && is_space (s.[!e]) do e := !e - 1 done; + if !e < !b then "" else String.sub s !b (!e - !b + 1) + let rec input_http_message file = let buf = Buffer.create 256 in let line = ref "POST / HTTP" in let msg_len = ref 0 in - while !line <> "" && !line <> "\r" do - line := input_line file; + while !line <> "" do + line := strip_spaces (input_line file); let line_len = String.length !line in - if line_len > 16 && String.sub !line 0 15 = "Content-length:" then + if line_len > 16 && String.sub !line 0 15 = "Content-length:" then ( msg_len := int_of_string (String.sub !line 16 (line_len - 16)); + ) done; Buffer.add_channel buf file !msg_len; Buffer.contents buf Modified: trunk/Toss/Formula/Aux.mli =================================================================== --- trunk/Toss/Formula/Aux.mli 2010-12-20 00:14:59 UTC (rev 1264) +++ trunk/Toss/Formula/Aux.mli 2010-12-20 02:05:24 UTC (rev 1265) @@ -168,7 +168,11 @@ val is_digit : char -> bool val is_letter : char -> bool val is_alphanum : char -> bool +val is_space : char -> bool +(** Strip spaces from left and right of a string. *) +val strip_spaces : string -> string + (** Printf helper functions. *) val list_fprint : (out_channel -> 'a -> unit) -> out_channel -> 'a list -> unit Modified: trunk/Toss/Play/GDL.ml =================================================================== --- trunk/Toss/Play/GDL.ml 2010-12-20 00:14:59 UTC (rev 1264) +++ trunk/Toss/Play/GDL.ml 2010-12-20 02:05:24 UTC (rev 1265) @@ -59,7 +59,7 @@ state := state_of_file "./examples/Tic-Tac-Toe.toss"; playing_as := player; game_description := game_descr; - player_name_terms := [|Const "X"; Const "O"|]; + player_name_terms := [|Const "XPLAYER"; Const "OPLAYER"|]; let effort, horizon, heur_adv_ratio = 2, 100, 4.0 in effort, horizon, heur_adv_ratio This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-20 00:15:06
|
Revision: 1264 http://toss.svn.sourceforge.net/toss/?rev=1264&view=rev Author: lukstafi Date: 2010-12-20 00:14:59 +0000 (Mon, 20 Dec 2010) Log Message: ----------- Order of argfind_max bug fix. Deterministic suggest setting (currently only ON for the GDL test). GDL suggestions only for played turn. Modified Paths: -------------- trunk/Toss/Formula/Aux.ml trunk/Toss/Formula/AuxTest.ml trunk/Toss/Play/GDL.ml trunk/Toss/Play/GDL.mli trunk/Toss/Play/Game.ml trunk/Toss/Play/Game.mli trunk/Toss/Play/GameTest.ml trunk/Toss/Play/Server.ml trunk/Toss/Play/ServerGDLTest.in trunk/Toss/Play/ServerGDLTest.out Modified: trunk/Toss/Formula/Aux.ml =================================================================== --- trunk/Toss/Formula/Aux.ml 2010-12-19 22:43:09 UTC (rev 1263) +++ trunk/Toss/Formula/Aux.ml 2010-12-20 00:14:59 UTC (rev 1264) @@ -236,9 +236,9 @@ let n = Array.length a in if n=0 then [] else - let best = ref (Array.unsafe_get a 0) - and besti = ref [0] in - for i = 1 to n-1 do + let best = ref (Array.unsafe_get a (n-1)) + and besti = ref [n-1] in + for i = n-2 downto 0 do let e = Array.unsafe_get a i in let res = cmp e !best in if res > 0 then (best := e; besti := [i]) Modified: trunk/Toss/Formula/AuxTest.ml =================================================================== --- trunk/Toss/Formula/AuxTest.ml 2010-12-19 22:43:09 UTC (rev 1263) +++ trunk/Toss/Formula/AuxTest.ml 2010-12-20 00:14:59 UTC (rev 1264) @@ -268,7 +268,7 @@ ); - "array_argfind, array_find_all, array_argfind_all" >:: + "array_argfind, array_find_all, array_argfind_all, array_argfind_all_max" >:: (fun () -> assert_equal ~printer:string_of_int 2 @@ -317,6 +317,13 @@ [] (Aux.array_argfind_all (fun e->e.[0]='e') [|"a";"c"; "b"|]); + + assert_equal + ~printer:(fun l->String.concat "; " (List.map string_of_int l)) + ~msg:"argfind_all_max" + [3;6] + (Aux.array_argfind_all_max (-) + [|2;3;2;5;3;4;5;1|]); ); "array_for_all, array_for_all2" >:: Modified: trunk/Toss/Play/GDL.ml =================================================================== --- trunk/Toss/Play/GDL.ml 2010-12-19 22:43:09 UTC (rev 1263) +++ trunk/Toss/Play/GDL.ml 2010-12-20 00:14:59 UTC (rev 1264) @@ -42,9 +42,9 @@ let compile_game_descr entries = entries -let client_player = ref (Const "uninitialized") +let playing_as = ref (Const "uninitialized") let game_description = ref [] -let game_state = ref (ref Arena.empty_state) +let player_name_terms = ref [| |] let state_of_file s = Printf.printf "GDL: Loading file %s...\n%!" s; @@ -56,31 +56,38 @@ res let initialize_game state player game_descr startcl = - game_state := state; - state := state_of_file "./examples/Tic-Tac-Toe.toss"; - - client_player := player; + playing_as := player; game_description := game_descr; + player_name_terms := [|Const "X"; Const "O"|]; let effort, horizon, heur_adv_ratio = 2, 100, 4.0 in effort, horizon, heur_adv_ratio let translate_last_action actions = - if actions = [] then - (* start of game -- Server will handle this answer as NOOP *) - "", [] - else - (* FIXME: really translate *) - "Cross", ["a1","a1"] + match actions with + | [] -> + (* start of game -- Server will handle this answer as NOOP *) + "", [] + | [Func ("MARK", [Const col; Const row]); Const "NOOP"] -> + "Cross", ["a1", + Structure.board_coords_name + (int_of_string col, int_of_string row)] + | [ Const "NOOP"; Func ("MARK", [Const col; Const row])] -> + "Circle", ["a1", + Structure.board_coords_name + (int_of_string col, int_of_string row)] + | _ -> assert false +let our_turn state = + let loc = state.Arena.cur_loc in + let loc_player = + state.Arena.game.Arena.graph.(loc).Arena.player in + !player_name_terms.(loc_player) = !playing_as + let translate_move rule emb new_state = let struc = new_state.Arena.struc in let elem = snd (List.hd emb) in let c, r = Structure.board_elem_coords (Structure.elem_str struc elem) in - let mark = Printf.sprintf "(MARK %d %d)" c r in - match rule with - | "Cross" -> "(" ^ mark ^ " NOOP)" - | "Circle" -> "(NOOP " ^ mark ^ ")" - | _ -> assert false + Printf.sprintf "(MARK %d %d)" c r Modified: trunk/Toss/Play/GDL.mli =================================================================== --- trunk/Toss/Play/GDL.mli 2010-12-19 22:43:09 UTC (rev 1263) +++ trunk/Toss/Play/GDL.mli 2010-12-20 00:14:59 UTC (rev 1264) @@ -31,11 +31,11 @@ type request = | Start of string * term * game_description * int * int - (* prepare game: match id, role, game, startclock, playclock *) + (** prepare game: match id, role, game, startclock, playclock *) | Play of string * term list - (* request a move: match id, actions on previous step *) + (** request a move: match id, actions on previous step *) | Stop of string * term list - (* game ends here: match id, actions on previous step *) + (** game ends here: match id, actions on previous step *) val compile_game_descr : game_descr_entry list -> game_description @@ -46,6 +46,9 @@ val translate_last_action : term list -> string * (string * string) list -(* Rule name, embedding, game state. *) +(** Whether the current player is the one being played as. *) +val our_turn : Arena.game_state -> bool + +(** Rule name, embedding, game state. *) val translate_move : string -> (int * int) list -> Arena.game_state -> string Modified: trunk/Toss/Play/Game.ml =================================================================== --- trunk/Toss/Play/Game.ml 2010-12-19 22:43:09 UTC (rev 1263) +++ trunk/Toss/Play/Game.ml 2010-12-20 00:14:59 UTC (rev 1264) @@ -10,6 +10,8 @@ let debug_level = ref 0 let set_debug_level i = (debug_level := i) +let deterministic_suggest = ref false + (* A global "hurry up!" switch triggered by the timer alarm. *) let timeout = ref false let get_timeout () = !timeout @@ -497,7 +499,7 @@ if rel < 0 then find best acc tl else if rel = 0 then find best (hd::acc) tl else find hd [hd] tl - | [] -> acc in + | [] -> List.rev acc in match l with | [] -> invalid_arg "find_all_max: empty list" | hd::tl -> find hd [hd] tl @@ -509,7 +511,8 @@ measure [subt_sizes]. Return a best position (randomized if multiple are optimal) and a best scores table (averaged if multiple are optimal). *) -let find_best_score cooperative player scores subt_sizes = +let find_best_score ?(use_det_setting=false) cooperative player + scores subt_sizes = (* find a new best score *) let my_scores = Array.map (fun s->s.(player)) scores in let bestsc = Aux.array_argfind_all_max compare my_scores in @@ -532,6 +535,9 @@ match bestsc with | [] -> failwith "impossible" | [bestsc,_] -> scores.(bestsc), bestsc + | (bsc,_)::(bsc2,_)::_ + when use_det_setting && !deterministic_suggest -> + scores.(bsc), bsc | _ -> (* pick ones from biggest subtrees *) let bestsc = @@ -823,7 +829,7 @@ let scores = Array.map (maximax_tree player betas (depth-1)) models in let _, best = - find_best_score cooperative player scores + find_best_score ~use_det_setting:true cooperative player scores (Array.map (fun _ -> 1) scores) in let state = models.(best) in (* {{{ log entry *) @@ -895,7 +901,8 @@ (uctree_score ~num_players subtree)) node.node_subtrees in let _, best = - find_best_score params.cooperative loc.Arena.player + find_best_score ~use_det_setting:true + params.cooperative loc.Arena.player scores (Array.map uctree_size node.node_subtrees) in let state = uctree_state node.node_subtrees.(best) in (* {{{ log entry *) Modified: trunk/Toss/Play/Game.mli =================================================================== --- trunk/Toss/Play/Game.mli 2010-12-19 22:43:09 UTC (rev 1263) +++ trunk/Toss/Play/Game.mli 2010-12-20 00:14:59 UTC (rev 1264) @@ -221,3 +221,7 @@ If > 1, print the updated gametree at each move using treesearch. *) val set_debug_level : int -> unit + +(** If true, do not randomize the final choice of move. Useful mostly + for debugging. *) +val deterministic_suggest : bool ref Modified: trunk/Toss/Play/GameTest.ml =================================================================== --- trunk/Toss/Play/GameTest.ml 2010-12-19 22:43:09 UTC (rev 1263) +++ trunk/Toss/Play/GameTest.ml 2010-12-20 00:14:59 UTC (rev 1264) @@ -564,17 +564,20 @@ "server: ServerGDLTest.in GDL Tic-Tac-Toe" >:: (fun () -> + let old_det_suggest = !Game.deterministic_suggest in + Game.deterministic_suggest := true; let in_ch = open_in "./Play/ServerGDLTest.in" in let out_ch = open_out "./Play/ServerGDLTest.temp" in (try while true do Server.req_handle in_ch out_ch done with End_of_file -> ()); close_in in_ch; close_out out_ch; + Game.deterministic_suggest := old_det_suggest; let result = Aux.input_file (open_in "./Play/ServerGDLTest.temp") in let target = Aux.input_file (open_in "./Play/ServerGDLTest.out") in - Sys.remove "./Play/ServerTest.temp"; + Sys.remove "./Play/ServerGDLTest.temp"; assert_equal ~printer:(fun x->x) target result ); Modified: trunk/Toss/Play/Server.ml =================================================================== --- trunk/Toss/Play/Server.ml 2010-12-19 22:43:09 UTC (rev 1263) +++ trunk/Toss/Play/Server.ml 2010-12-20 00:14:59 UTC (rev 1264) @@ -152,6 +152,7 @@ let req = req_of_str line in let resp = match req with + | Aux.Left (Arena.SuggestLocMoves (loc, timer, effort, how, horizon, heuristic, heur_adv_ratio)) -> ( @@ -241,8 +242,9 @@ time = !state.Arena.time; loc = !state.Arena.cur_loc} pos memory | _ -> failwith "req_handle: impossible" in - state := new_state; (* Rewriting doesn't handle location update. *) + state := + {new_state with Arena.cur_loc = moves.(pos).Game.next_loc}; let new_game_state = { Game.struc = new_state.Arena.struc; loc = moves.(pos).Game.next_loc; @@ -282,157 +284,175 @@ GDL.translate_last_action actions in if r_name <> "" then ( - let {Arena.rules=rules; graph=graph} = !state.Arena.game in - let struc = !state.Arena.struc in - let fn s n = Structure.find_elem s n in - let r = List.assoc r_name rules in - let lhs = - r.ContinuousRule.discrete.DiscreteRule.lhs_struc in - let m = - List.map (fun (l, s) -> (fn lhs l, fn struc s)) mtch in - let moves = - Game.gen_moves Game.cGRID_SIZE rules - !state.Arena.struc graph.(!state.Arena.cur_loc) in - let pos = - (try - for i = 0 to Array.length moves - 1 do + let {Arena.rules=rules; graph=graph} = !state.Arena.game in + let struc = !state.Arena.struc in + let fn s n = Structure.find_elem s n in + let r = List.assoc r_name rules in + let lhs = + r.ContinuousRule.discrete.DiscreteRule.lhs_struc in + let m = + List.map (fun (l, s) -> (fn lhs l, fn struc s)) mtch in + let moves = + Game.gen_moves Game.cGRID_SIZE rules + !state.Arena.struc graph.(!state.Arena.cur_loc) in + let pos = + (try + for i = 0 to Array.length moves - 1 do (* FIXME: handle time and params! *) - let mov = moves.(i) in + let mov = moves.(i) in (* {{{ log entry *) - if !debug_level > 1 then ( - Printf.printf "GDL: considering move %s\n%!" - (Game.move_gs_str !state mov) - ); + if !debug_level > 3 then ( + Printf.printf "GDL: for %s considering move %s\n%!" + r_name (Game.move_gs_str !state mov) + ); (* }}} *) - if - r_name = mov.Game.rule && + if + r_name = mov.Game.rule && (* t = mov.Game.time && *) (* something wrong with this: List.for_all (fun (pn, pv) -> pv = List.assoc pn mov.Game.parameters) p && *) - List.for_all (fun (e, f) -> - f = List.assoc e mov.Game.embedding) m + List.for_all (fun (e, f) -> + f = List.assoc e mov.Game.embedding) m (* TODO: handle location matching *) - then ( - expected_location := mov.Game.next_loc; - let _ = if !debug_level > 2 then - Printf.printf "expected_location = %d\n%!" - !expected_location in - raise (Found i)) - done; + then ( + expected_location := mov.Game.next_loc; + let _ = if !debug_level > 2 then + Printf.printf "expected_location = %d\n%!" + !expected_location in + raise (Found i)) + done; (* TODO: if not due to only time or params mismatch, block or warn about invalid rule application *) - - failwith - "Server GDL Play request: action mismatched with play state" - with Found pos -> pos) in - let old_struc = !state.Arena.struc in - let req = Arena.ApplyRule (r_name, mtch, 0.1, []) in - let (new_state, resp) = Arena.handle_request !state req in - let memory = match !play, !play_state with - | Some play, Some {Game.memory=memory; game_state=pstate} -> - Game.update_memory - ~num_players:play.Game.game.Arena.num_players - {Game.struc=old_struc; - time = !state.Arena.time; - loc = !state.Arena.cur_loc} pos memory - | _ -> failwith "req_handle: impossible" in - state := new_state; + + failwith + "Server GDL Play request: action mismatched with play state" + with Found pos -> pos) in + let old_struc = !state.Arena.struc in + let req = Arena.ApplyRule (r_name, mtch, 0.1, []) in + let (new_state, resp) = Arena.handle_request !state req in + let memory = match !play, !play_state with + | Some play, Some {Game.memory=memory; game_state=pstate} -> + Game.update_memory + ~num_players:play.Game.game.Arena.num_players + {Game.struc=old_struc; + time = !state.Arena.time; + loc = !state.Arena.cur_loc} pos memory + | _ -> failwith "req_handle: impossible" in (* Rewriting doesn't handle location update. *) - let new_game_state = { - Game.struc = new_state.Arena.struc; - loc = moves.(pos).Game.next_loc; - time = new_state.Arena.time; - } in - play_state := Some { - Game.game_state = new_game_state; - memory = memory; - }); - - let time_used = - time_started - (int_of_float (ceil (Sys.time ()))) in - let p, ps = - match !play, !play_state with - | Some play, Some play_state -> - play, play_state - | _ -> assert false in - ignore (Unix.alarm (!playclock - time_used)); - let res = Game.suggest p ps in - Game.cancel_timeout (); - let mov_msg = - match res with - | Some (move, new_state) -> - play_state := Some new_state; - GDL.translate_move move.Game.rule move.Game.embedding - !state - | None -> "NOOP" in - let msg_len = String.length mov_msg in - "HTTP/1.0 200 OK\r\nContent-type: text/acl\r\nContent-length: " - ^ string_of_int msg_len ^ "\r\n\r\n" ^ mov_msg + state := + {new_state with Arena.cur_loc = moves.(pos).Game.next_loc}; + let new_game_state = { + Game.struc = new_state.Arena.struc; + loc = moves.(pos).Game.next_loc; + time = new_state.Arena.time; + } in + play_state := Some { + Game.game_state = new_game_state; + memory = memory; + }); + if GDL.our_turn !state + then + let time_used = + time_started - (int_of_float (ceil (Sys.time ()))) in + let p, ps = + match !play, !play_state with + | Some play, Some play_state -> + play, play_state + | _ -> assert false in + ignore (Unix.alarm (!playclock - time_used)); + let res = Game.suggest p ps in + Game.cancel_timeout (); + let mov_msg = + match res with + | Some (move, new_state) -> + (* Do not change state yet! *) + GDL.translate_move move.Game.rule move.Game.embedding + !state + | None -> "NOOP" in + let msg_len = String.length mov_msg in + "HTTP/1.0 200 OK\r\nContent-type: text/acl\r\nContent-length: " + ^ string_of_int msg_len ^ "\r\n\r\n" ^ mov_msg + else + "HTTP/1.0 200 OK\r\nContent-type: text/acl\r\nContent-length: " + ^ "4\r\n\r\nNOOP" + + | Aux.Right (GDL.Stop (_, actions)) -> + let time_started = int_of_float (Sys.time ()) in let r_name, mtch = GDL.translate_last_action actions in - let {Arena.rules=rules; graph=graph} = !state.Arena.game in - let struc = !state.Arena.struc in - let fn s n = Structure.find_elem s n in - let r = List.assoc r_name rules in - let lhs = - r.ContinuousRule.discrete.DiscreteRule.lhs_struc in - let m = - List.map (fun (l, s) -> (fn lhs l, fn struc s)) mtch in - let moves = - Game.gen_moves Game.cGRID_SIZE rules - !state.Arena.struc graph.(!state.Arena.cur_loc) in - let pos = - (try - for i = 0 to Array.length moves - 1 do + if r_name <> "" then ( + let {Arena.rules=rules; graph=graph} = !state.Arena.game in + let struc = !state.Arena.struc in + let fn s n = Structure.find_elem s n in + let r = List.assoc r_name rules in + let lhs = + r.ContinuousRule.discrete.DiscreteRule.lhs_struc in + let m = + List.map (fun (l, s) -> (fn lhs l, fn struc s)) mtch in + let moves = + Game.gen_moves Game.cGRID_SIZE rules + !state.Arena.struc graph.(!state.Arena.cur_loc) in + let pos = + (try + for i = 0 to Array.length moves - 1 do (* FIXME: handle time and params! *) - let mov = moves.(i) in - if - r_name = mov.Game.rule && + let mov = moves.(i) in + (* {{{ log entry *) + if !debug_level > 3 then ( + Printf.printf "GDL: for %s considering move %s\n%!" + r_name (Game.move_gs_str !state mov) + ); + (* }}} *) + if + r_name = mov.Game.rule && (* t = mov.Game.time && *) (* something wrong with this: List.for_all (fun (pn, pv) -> pv = List.assoc pn mov.Game.parameters) p && *) - List.for_all (fun (e, f) -> - f = List.assoc e mov.Game.embedding) m + List.for_all (fun (e, f) -> + f = List.assoc e mov.Game.embedding) m (* TODO: handle location matching *) - then ( - expected_location := mov.Game.next_loc; - let _ = if !debug_level > 2 then - Printf.printf "expected_location = %d\n%!" - !expected_location in - raise (Found i)) - done; + then ( + expected_location := mov.Game.next_loc; + let _ = if !debug_level > 2 then + Printf.printf "expected_location = %d\n%!" + !expected_location in + raise (Found i)) + done; (* TODO: if not due to only time or params mismatch, block or warn about invalid rule application *) - failwith - "Server GDL Play request: action mismatched with play state" - with Found pos -> pos) in - let old_struc = !state.Arena.struc in - let req = Arena.ApplyRule (r_name, mtch, 0.1, []) in - let (new_state, resp) = Arena.handle_request !state req in - let memory = match !play, !play_state with - | Some play, Some {Game.memory=memory; game_state=pstate} -> - Game.update_memory - ~num_players:play.Game.game.Arena.num_players - {Game.struc=old_struc; - time = !state.Arena.time; - loc = !state.Arena.cur_loc} pos memory - | _ -> failwith "req_handle: impossible" in - state := new_state; + + failwith + "Server GDL Stop request: action mismatched with play state" + with Found pos -> pos) in + let old_struc = !state.Arena.struc in + let req = Arena.ApplyRule (r_name, mtch, 0.1, []) in + let (new_state, resp) = Arena.handle_request !state req in + let memory = match !play, !play_state with + | Some play, Some {Game.memory=memory; game_state=pstate} -> + Game.update_memory + ~num_players:play.Game.game.Arena.num_players + {Game.struc=old_struc; + time = !state.Arena.time; + loc = !state.Arena.cur_loc} pos memory + | _ -> failwith "req_handle: impossible" in (* Rewriting doesn't handle location update. *) - let new_game_state = { - Game.struc = new_state.Arena.struc; - loc = moves.(pos).Game.next_loc; - time = new_state.Arena.time; - } in - play_state := Some { - Game.game_state = new_game_state; - memory = memory; - }; + state := + {new_state with Arena.cur_loc = moves.(pos).Game.next_loc}; + let new_game_state = { + Game.struc = new_state.Arena.struc; + loc = moves.(pos).Game.next_loc; + time = new_state.Arena.time; + } in + play_state := Some { + Game.game_state = new_game_state; + memory = memory; + }); + "HTTP/1.0 200 OK\r\nContent-type: text/acl\r\nContent-length: 4" ^ "\r\n\r\nDONE" Modified: trunk/Toss/Play/ServerGDLTest.in =================================================================== --- trunk/Toss/Play/ServerGDLTest.in 2010-12-19 22:43:09 UTC (rev 1263) +++ trunk/Toss/Play/ServerGDLTest.in 2010-12-20 00:14:59 UTC (rev 1264) @@ -32,7 +32,7 @@ Content-type: text/acl Content-length: 41 -(PLAY MATCH.3316980891 (NOOP (MARK 1 1))) +(PLAY MATCH.3316980891 (NOOP (MARK 3 1))) POST / HTTP/1.0 Accept: text/delim @@ -41,7 +41,7 @@ Content-type: text/acl Content-length: 41 -(PLAY MATCH.3316980891 ((MARK 2 2) NOOP)) +(PLAY MATCH.3316980891 ((MARK 2 1) NOOP)) POST / HTTP/1.0 Accept: text/delim @@ -50,7 +50,7 @@ Content-type: text/acl Content-length: 41 -(PLAY MATCH.3316980891 (NOOP (MARK 1 2))) +(PLAY MATCH.3316980891 (NOOP (MARK 2 3))) POST / HTTP/1.0 Accept: text/delim @@ -59,4 +59,13 @@ Content-type: text/acl Content-length: 41 -(STOP MATCH.3316980891 ((MARK 1 1) NOOP)) +(PLAY MATCH.3316980891 ((MARK 3 3) NOOP)) + +POST / HTTP/1.0 +Accept: text/delim +Sender: GAMEMASTER +Receiver: GAMEPLAYER +Content-type: text/acl +Content-length: 41 + +(STOP MATCH.3316980891 (NOOP (MARK 1 1))) Modified: trunk/Toss/Play/ServerGDLTest.out =================================================================== --- trunk/Toss/Play/ServerGDLTest.out 2010-12-19 22:43:09 UTC (rev 1263) +++ trunk/Toss/Play/ServerGDLTest.out 2010-12-20 00:14:59 UTC (rev 1264) @@ -1,36 +1,41 @@ -HTTP/1.0 200 OK -Content-type: text/acl -Content-length: 5 - +HTTP/1.0 200 OK +Content-type: text/acl +Content-length: 5 + READY -HTTP/1.0 200 OK -Content-type: text/acl -Content-length: 10 - +HTTP/1.0 200 OK +Content-type: text/acl +Content-length: 10 + (MARK 2 2) -HTTP/1.0 200 OK -Content-type: text/acl -Content-length: 4 - +HTTP/1.0 200 OK +Content-type: text/acl +Content-length: 4 + NOOP -HTTP/1.0 200 OK -Content-type: text/acl -Content-length: 10 - -(MARK 2 2) -HTTP/1.0 200 OK -Content-type: text/acl -Content-length: 4 - +HTTP/1.0 200 OK +Content-type: text/acl +Content-length: 10 + +(MARK 2 1) +HTTP/1.0 200 OK +Content-type: text/acl +Content-length: 4 + NOOP -HTTP/1.0 200 OK -Content-type: text/acl -Content-length: 10 - -(MARK 1 1) -HTTP/1.0 200 OK -Content-type: text/acl -Content-length: 4 - +HTTP/1.0 200 OK +Content-type: text/acl +Content-length: 10 + +(MARK 3 3) +HTTP/1.0 200 OK +Content-type: text/acl +Content-length: 4 + +NOOP +HTTP/1.0 200 OK +Content-type: text/acl +Content-length: 4 + DONE ERR processing completed -- EOF This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-19 22:43:16
|
Revision: 1263 http://toss.svn.sourceforge.net/toss/?rev=1263&view=rev Author: lukaszkaiser Date: 2010-12-19 22:43:09 +0000 (Sun, 19 Dec 2010) Log Message: ----------- Move suggestions and computer play in WebClient. Modified Paths: -------------- trunk/Toss/WebClient/Handler.py trunk/Toss/WebClient/Main.js trunk/Toss/WebClient/MakeDB.py trunk/Toss/WebClient/README trunk/Toss/WebClient/Style.css trunk/Toss/WebClient/Wrapper.py trunk/Toss/WebClient/index.html trunk/Toss/WebClient/profile.html trunk/Toss/WebClient/register.html trunk/Toss/examples/Breakthrough.toss trunk/Toss/examples/Chess.toss trunk/Toss/examples/Gomoku.toss trunk/Toss/examples/Tic-Tac-Toe.toss Added Paths: ----------- trunk/Toss/WebClient/contact.html Modified: trunk/Toss/WebClient/Handler.py =================================================================== --- trunk/Toss/WebClient/Handler.py 2010-12-19 20:42:04 UTC (rev 1262) +++ trunk/Toss/WebClient/Handler.py 2010-12-19 22:43:09 UTC (rev 1263) @@ -69,7 +69,7 @@ or_s = "(player1='" + player_id + "' or player2='" + player_id + "')" plays = get_all_from_db (db, "cur_states", "game='"+ game + "' and " + or_s) def play_name (p): - (pid, g, p1, p2, move, _, _, _) = p + (pid, g, p1, p2, move, _, _, _, _) = p return ("/plays/" + str(g) + "_" + str(p1) + "_" + str(p2) + "_" + str(pid) + "_" + str(move)) return (str([play_name (p) for p in plays])) @@ -78,14 +78,14 @@ friends = get_all_from_db (db, "friends", "id='"+ uid + "'") return (str([str(f) for (_, f) in friends])) -def db_cur_insert (db, game, p1, p2, pid, move, toss, info, svg_str): - db.execute ("insert into cur_states(playid, game, player1, player2, move, toss, info, svg) values (?, ?, ?, ?, ?, ?, ?, ?)", - (pid, game, p1, p2, move, toss, info, svg_str)) +def db_cur_insert (db, game, p1, p2, pid, move, toss, loc, info, svg_str): + db.execute ("insert into cur_states(playid, game, player1, player2, move, toss, loc, info, svg) values (?, ?, ?, ?, ?, ?, ?, ?, ?)", + (pid, game, p1, p2, move, toss, str(loc), info, svg_str)) db.commit () -def db_old_insert (db, game, p1, p2, pid, move, toss, info, svg_str): - db.execute ("insert into old_states(playid, game, player1, player2, move, toss, info, svg) values (?, ?, ?, ?, ?, ?, ?, ?)", - (pid, game, p1, p2, move, toss, info, svg_str)) +def db_old_insert (db, game, p1, p2, pid, move, toss, loc, info, svg_str): + db.execute ("insert into old_states(playid, game, player1, player2, move, toss, loc, info, svg) values (?, ?, ?, ?, ?, ?, ?, ?, ?)", + (pid, game, p1, p2, move, toss, str(loc), info, svg_str)) db.commit () def get_game_info (client): @@ -107,9 +107,10 @@ client.open_from_str (toss) info = get_game_info (client) model = client.get_model () + loc = client.get_cur_loc () get_global_lock (db) pid = get_free_id (db) - db_cur_insert (db, game, p1, p2, pid, move, model, info, "") + db_cur_insert (db, game, p1, p2, pid, move, model, loc, info, "") release_global_lock (db) return (str(pid) + "$" + info) @@ -120,7 +121,7 @@ def open_db (db, game, p1, p2, pid, move): select_s = game_select_s (game, p1, p2, pid, move) res = get_all_from_db (db, "cur_states", select_s) - (_, _, _, _, _, _, info, _) = res[0] + (_, _, _, _, _, _, _, info, _) = res[0] return (info) def db_escape (s): @@ -129,10 +130,11 @@ def move_play (db, client, move_tup, g, p1, p2, pid, m): sel_s = game_select_s (g, p1, p2, pid, m) old_res = get_all_from_db (db, "cur_states", sel_s) - (_, _, _, _, _, old_toss, old_info, old_svg) = old_res[0] + (_, _, _, _, _, old_toss, old_loc, old_info, old_svg) = old_res[0] res = get_all_from_db (db, "games", "game='" + g + "'") (_, game_toss) = res[0] client.open_from_str (game_toss + "\n MODEL " + old_toss) + client.set_cur_loc (old_loc) (move1, move2, move3) = move_tup client.make_move (move1, move2, move3) new_toss = db_escape (client.get_model ()) @@ -140,8 +142,9 @@ new_info_db = db_escape (new_info) db.execute ("update cur_states set toss='" + new_toss + "' where " + sel_s) db.execute ("update cur_states set info='"+ new_info_db +"' where "+ sel_s) + db.execute ("update cur_states set loc='"+ str(move3) +"' where "+ sel_s) db.execute ("update cur_states set move=" + str(int(m)+1) +" where "+ sel_s) - db_old_insert (db, g, p1, p2, pid, m, old_toss, old_info, old_svg) + db_old_insert (db, g, p1, p2, pid, m, old_toss, old_loc, old_info, old_svg) return (new_info) def upd_svg (db, g, p1, p2, pid, m, svg_s): @@ -187,6 +190,7 @@ if passwd_from_db (db, uid): return (False) db.execute ("insert into users(id, name, surname, email, passwd) " + "values (?, ?, ?, ?, ?)", (uid, name, surname, email, pwd)) + db.execute ("insert into friends(id, fid) values (?, ?)", (uid, "computer")) db.commit () return (True) @@ -236,6 +240,26 @@ plays += "$" + list_plays (db, g, usr) return (usr + "$" + name + plays) +def suggest_offset (offset, db, client, g, p1, p2, pid, m): + sel_s = game_select_s (g, p1, p2, pid, m) + res = get_all_from_db (db, "cur_states", sel_s) + (_, _, _, _, _, toss, loc, _, _) = res[0] + game_res = get_all_from_db (db, "games", "game='" + g + "'") + (_, game_toss) = game_res[0] + client.open_from_str (game_toss + "\n MODEL " + toss) + client.set_cur_loc (loc) + depth = client.get_data ("depth") + if depth == "none": depth = 2 + adv_ratio = client.get_data ("adv_ratio") + if adv_ratio == "none": adv_ratio = 2 + return (client.suggest (int(depth) + offset, adv_ratio)) + +def suggest (db, client, g, p1, p2, pid, m): + return (suggest_offset (0, db, client, g, p1, p2, pid, m)) + +def suggestx (db, client, g, p1, p2, pid, m): + return (suggest_offset (1, db, client, g, p1, p2, pid, m)) + def handler(req): req.content_type = "text/plain" db = sqlite3.connect(MakeDB.DB_FILE) @@ -300,7 +324,8 @@ res = eval (cmd.lower() + "(db, " + data + ")") req.write(str(res)) return apache.OK - if (cmd == "NEW_PLAY") or (cmd == "MOVE_PLAY"): + if ((cmd == "NEW_PLAY") or (cmd == "MOVE_PLAY") or + (cmd == "SUGGEST") or (cmd == "SUGGESTX")): port = get_toss_port (db) c = SystemClient ("localhost", port) res = eval (cmd.lower() + "(db, " + data + ")") Modified: trunk/Toss/WebClient/Main.js =================================================================== --- trunk/Toss/WebClient/Main.js 2010-12-19 20:42:04 UTC (rev 1262) +++ trunk/Toss/WebClient/Main.js 2010-12-19 22:43:09 UTC (rev 1263) @@ -191,9 +191,9 @@ function make_move () { if (CUR_MOVE == "") return; var m = PLAYS[CUR_PLAY_I][3] % 2; - if (PLAYS[CUR_PLAY_I][m] != UNAME) { - alert ("It is your Opponent's turn"); - return; + if (PLAYS[CUR_PLAY_I][m] != UNAME && PLAYS[CUR_PLAY_I][m] != "computer") { + alert ("It is your Opponent's turn"); + return; } document.getElementById("working").style.display = "block"; var info = srv("MOVE_PLAY", 'c, '+ CUR_MOVE +', '+ play_py_id (CUR_PLAY_I)); @@ -209,9 +209,14 @@ full_redraw (); PLAYS[CUR_PLAY_I][3] = parseInt(PLAYS[CUR_PLAY_I][3]) + 1; async_srv ("UPD_SVG", play_py_id(CUR_PLAY_I) + ", " + svg_string()); - var old_li = document.getElementById ("plays-list-" + GAME_NAME + "-elem-" + CUR_PLAY_I); + var old_li = document.getElementById ("plays-list-" + GAME_NAME + + "-elem-" + CUR_PLAY_I); var li = new_play_item (GAME_NAME, CUR_PLAY_I); old_li.parentNode.replaceChild (li, old_li); + if (PLAYS[CUR_PLAY_I][(m + 1) % 2] == "computer") { + suggest_move (); + make_move (); + } } @@ -337,3 +342,26 @@ var lst = srv ("LIST_FRIENDS", "user"); FRIENDS = convert_python_list (',', lst); } + +function suggest_move () { + var m = srv("SUGGEST", 'c, '+ play_py_id (CUR_PLAY_I)); + show_move (m); +} + +function suggest_move_better () { + var m = srv("SUGGESTX", 'c, '+ play_py_id (CUR_PLAY_I)); + show_move (m); +} + +function toggle_suggestions () { + var txt = document.getElementById("suggestions-toggle").innerHTML; + if (txt.indexOf ("Show") == -1) { + document.getElementById("suggestions-toggle").innerHTML = + "Show Move Suggestions"; + document.getElementById("player-info-par").style.display = "none"; + } else { + document.getElementById("suggestions-toggle").innerHTML = + "Hide Move Suggestions"; + document.getElementById("player-info-par").style.display = "block"; + } +} \ No newline at end of file Modified: trunk/Toss/WebClient/MakeDB.py =================================================================== --- trunk/Toss/WebClient/MakeDB.py 2010-12-19 20:42:04 UTC (rev 1262) +++ trunk/Toss/WebClient/MakeDB.py 2010-12-19 22:43:09 UTC (rev 1263) @@ -20,10 +20,10 @@ " name string, surname string, email string, passwd string)") conn.execute("create table cur_states(playid int primary key," + " game string, player1 string, player2 string," + - " move int, toss string, info string, svg string)") + " move int, toss string, loc string, info string, svg string)") conn.execute("create table old_states(playid int," + " game string, player1 string, player2 string," + - " move int, toss string, info string, svg string)") + " move int, toss string, loc string, info string, svg string)") conn.execute("create table games(game string primary key, toss string)") conn.execute("create table ports(port int primary key, locked bool)") conn.execute("create table lock(tid int primary key, locked bool)") @@ -31,6 +31,9 @@ conn.commit () conn.execute ("insert into lock(tid, locked) values (?, ?)", (TUID, 'false')) + conn.execute ("insert into users(id, name, surname, email, passwd) values"+ + " (?, ?, ?, ?, ?)", + ("computer", "Computer", "tPlay", "co...@tp...", "xxx")) for g in games: f = open(games_path + "/" + g + ".toss") toss = f.read() Modified: trunk/Toss/WebClient/README =================================================================== --- trunk/Toss/WebClient/README 2010-12-19 20:42:04 UTC (rev 1262) +++ trunk/Toss/WebClient/README 2010-12-19 22:43:09 UTC (rev 1263) @@ -14,13 +14,13 @@ The main handler script is called Hander.py (server side) and corresponding JavaScript functions are in *.js. To start client open index.html, but first make sure that WebClient is linked in /var/www (ln -s should suffice). -Then run "./make_db" from WebClient and make sure Handler entry (above) is ok. +Then run "./MakeDB.py" from WebClient and make sure Handler entry (above) is ok. Also copy Server from main Toss dir as TossServer to the WebClient directory. TODO: - move interface: first click all, second click toggle, if one - confirm msg - - move suggestions and play against computer + - display results, prevent suggestion bug when game has already ended - sort plays by who's turn it is - option to give up game and offer a draw - enable google (or other) analytics Modified: trunk/Toss/WebClient/Style.css =================================================================== --- trunk/Toss/WebClient/Style.css 2010-12-19 20:42:04 UTC (rev 1262) +++ trunk/Toss/WebClient/Style.css 2010-12-19 22:43:09 UTC (rev 1263) @@ -35,6 +35,7 @@ #plays .bt { width: 7em; + font-size: 0.75em; position: absolute; right: 2px; } @@ -248,7 +249,9 @@ padding: 0px; margin: 0px; height: 1.3em; - text-align: right; + text-align: center; + font-size: 0.9em; + font-weight: bold; color: #ffe4aa; background-color: #400827; border-color: #260314; @@ -256,6 +259,47 @@ border-width: 5px 0px 0px 0px; } +#bottom a, #bottom a:link, #bottom a:active, #bottom a:visited { + color: #ffe4aa; + text-decoration: none; +} + +#bottom a:hover { + color: #ffffff; + text-decoration: underline; + cursor: pointer; +} + +/* Bottom styles. */ + +#contact { + position: absolute; + top: 0px; + right: 0.5em; +} + +#suggestions-toggle { + position: absolute; + margin: 0px; + padding: 0px; + top: 0px; + left: 0.5em; + border: 0px; + background-color: #400827; + color: #ffe4aa; + font-family: Verdana, 'TeXGyreHerosRegular', sans; + font-size: 1em; + font-weight: bold; +} + +#suggestions-toggle:hover { + color: #ffffff; + text-decoration: underline; + cursor: pointer; +} + +/* Menu styles. */ + #menu-top-par { margin-top: 0.5em; margin-bottom: 0em; @@ -321,13 +365,27 @@ text-decoration: underline; } +#register-content { + position: relative; + top: 2.5em; + left: 1em; +} +#main-profile { + position: relative; + left: 1em; +} + #opponents { display: none; position: absolute; - left: 6em; - top: 3.5em; + left: 0px; + right: 0px; + top: 4em; min-width: 20em; + width: 20em; + margin-left: auto; + margin-right: auto; color: #ffe4aa; background-color: #400827; font-weight: bold; @@ -383,7 +441,8 @@ #welcome { text-align: justify; - margin-top: 1em; + margin-top: 3.5em; + margin-left: 1em; } #welcome-top { @@ -410,6 +469,12 @@ padding: 0px; } +#player-info-par { + display: none; + margin-top: 0.5em; + padding: 0px; +} + #move-info-par { margin-top: 0.5em; padding: 0px; @@ -461,7 +526,8 @@ .game-par { padding: 0px; - border-top: 0px solid #260314; + padding-bottom: 0.2em; + border-bottom: 1px solid #260314; } #plays { @@ -500,7 +566,6 @@ } - /* SVG styling */ #svg { min-width: 10em; Modified: trunk/Toss/WebClient/Wrapper.py =================================================================== --- trunk/Toss/WebClient/Wrapper.py 2010-12-19 20:42:04 UTC (rev 1262) +++ trunk/Toss/WebClient/Wrapper.py 2010-12-19 22:43:09 UTC (rev 1263) @@ -197,3 +197,33 @@ self.apply_rule (r, m, 1.0, []) self.set_cur_loc (endp) return ("move ok") + + def get_data (self, did): + m = self.msg ("GET DATA " + did) + if len(m) < 3: return (m) + if m[0:3] == "ERR": return ("none") + return (m) + + def set_time (self, tstep, t): + m = self.msg ("SET dynamics " + repr(tstep) + " " + repr(t)) + return (m) + + def get_time (self): + m = self.msg ("GET dynamics") + t = [s.strip() for s in m.split('/')] + return ((float(t[0]), float(t[1]))) + + def suggest (self, depth, adv_ratio): + loc = self.get_cur_loc () + (ts, t) = self.get_time () + m = self.msg ("EVAL LOC MOVES " + str(adv_ratio) + ".0 " + + str(loc) +" TIMEOUT 1200 "+ str(depth) + + " alpha_beta_ord") + self.set_time (ts, t) + msg = [s.strip() for s in m.split(';')] + emb = dict() + for s in msg[1].split(','): + es = [x.strip() for x in s.split(':')] + emb[es[0]] = es[1] + # we ignore params in html for now + return ((emb, msg[0], int(msg[3]))) Added: trunk/Toss/WebClient/contact.html =================================================================== --- trunk/Toss/WebClient/contact.html (rev 0) +++ trunk/Toss/WebClient/contact.html 2010-12-19 22:43:09 UTC (rev 1263) @@ -0,0 +1,35 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg" xml:lang="en" lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/xhtml+xml; charset=UTF-8" /> + <title>tPlay — Contact</title> + <meta http-equiv="X-UA-Compatible" content="chrome=1"> + <link rel="icon" type="image/vnd.microsoft.icon" href="/favicon.ico" /> + <link href="fontstyle.css" media="screen" rel="stylesheet" type="text/css" /> + <link rel="stylesheet" type="text/css" href="Style.css" media="screen" title="Default"/> +</head> + +<body> +<div id="top"> +<div id="logo"><a href="index.html">tPlay</a></div> +</div> + +<div id="main"> + +<div id="register-content"> + +<h2>Contact tPlay</h2> + +Just write us an email! + +</div> + +</div> + +<div id="bottom"> +<a href="http://toss.sourceforge.net" id="toss-link">Powered by Toss</a> +<a href="contact.html" id="contact">Contact and Info</a> +</div> + +</body> +</html> Modified: trunk/Toss/WebClient/index.html =================================================================== --- trunk/Toss/WebClient/index.html 2010-12-19 20:42:04 UTC (rev 1262) +++ trunk/Toss/WebClient/index.html 2010-12-19 22:43:09 UTC (rev 1263) @@ -129,8 +129,7 @@ <div id="game-disp"> <p id="game-info-par"> <span id="game-title"></span> - game <span id="play-number">?</span>, - <span id="cur-player"></span> moving + game <span id="play-number">?</span> </p> <p id="move-info-par"> @@ -138,13 +137,27 @@ <span id="cur-move">none</span> </p> + <p id="player-info-par"> + Moving: <span id="cur-player">?</span> + <button id="sugbt" class="bt" onclick="suggest_move()"> + Suggest (weak, fast) + </button> + <button id="sugbt" class="bt" onclick="suggest_move_better()"> + Suggest (stronger, slow) + </button> + </p> + <div id="board"><div id="working">Working...</div></div> </div> </div> <div id="bottom"> -<div style="margin-right: 0em; display: none;">Disclaimer</div> +<button id="suggestions-toggle" onclick="toggle_suggestions()"> + Show Move Suggestions +</button> +<a href="http://toss.sourceforge.net" id="toss-link">Powered by Toss</a> +<a href="contact.html" id="contact">Contact and Info</a> </div> </body> Modified: trunk/Toss/WebClient/profile.html =================================================================== --- trunk/Toss/WebClient/profile.html 2010-12-19 20:42:04 UTC (rev 1262) +++ trunk/Toss/WebClient/profile.html 2010-12-19 22:43:09 UTC (rev 1263) @@ -94,7 +94,8 @@ </div> <div id="bottom"> -<div style="margin-right: 0em; display: none;">Disclaimer</div> +<a href="http://toss.sourceforge.net" id="toss-link">Powered by Toss</a> +<a href="contact.html" id="contact">Contact and Info</a> </div> </body> Modified: trunk/Toss/WebClient/register.html =================================================================== --- trunk/Toss/WebClient/register.html 2010-12-19 20:42:04 UTC (rev 1262) +++ trunk/Toss/WebClient/register.html 2010-12-19 22:43:09 UTC (rev 1263) @@ -19,6 +19,8 @@ <div id="main"> +<div id="register-content"> + <h2>Register on tPlay</h2> <form id="registerform"> @@ -45,8 +47,11 @@ </div> +</div> + <div id="bottom"> -<div style="margin-right: 0em; display: none;">Disclaimer</div> +<a href="http://toss.sourceforge.net" id="toss-link">Powered by Toss</a> +<a href="contact.html" id="contact">Contact and Info</a> </div> </body> Modified: trunk/Toss/examples/Breakthrough.toss =================================================================== --- trunk/Toss/examples/Breakthrough.toss 2010-12-19 20:42:04 UTC (rev 1262) +++ trunk/Toss/examples/Breakthrough.toss 2010-12-19 22:43:09 UTC (rev 1263) @@ -1,19 +1,14 @@ PLAYERS 1, 2 -DATA depth: 3 -RULE WhiteLeft: - [ | B:1 {} | ] " - - ?B ? - - ? W -" -> [ | B:1 {} | - ] " - - W ? - - ? . -" emb W, B - pre not ex x (B(x) and not ex y C(y, x)) +DATA depth: 2, adv_ratio: 2 +REL DiagW (x, y) = ex z (C(x, z) and (R(y, z) or R(z, y))) +REL DiagB (x, y) = ex z (C(z, x) and (R(y, z) or R(z, y))) +RULE WhiteDiag: + [ a, b | W { a }; _opt_B { b } | + vx {a->0.,b->10.}; vy {a->0.,b->0.}; x {a->0.,b->10.}; y {a->0.,b->10.} ] + -> + [ a, b | W { b } | + vx {a->0.,b->10.}; vy {a->0.,b->0.}; x {a->0.,b->10.}; y {a->0.,b->10.} ] + emb W, B pre DiagW(a, b) and not ex x (B(x) and not ex y C(y, x)) RULE WhiteStraight: [ | B:1 {}; R:2 {} | ] " @@ -27,34 +22,13 @@ . " emb W, B pre not ex x (B(x) and not ex y C(y, x)) -RULE WhiteRight: - [ | B:1 {} | ] " - - ? ?B - - W ? -" -> [ | B:1 {} | - ] " - - ? W - - . ? -" emb W, B - pre not ex x (B(x) and not ex y C(y, x)) -RULE BlackLeft: - [ | W:1 {} | ] " - - B ? - - ? ?W -" -> [ | W:1 {} | - ] " - - . ? - - ? B -" emb W, B - pre not ex x (W(x) and not ex y C(x, y)) +RULE BlackDiag: + [ a, b | B { a }; _opt_W { b } | + vx {a->0.,b->10.}; vy {a->0.,b->0.}; x {a->0.,b->10.}; y {a->0.,b->10.} ] + -> + [ a, b | B { b } | + vx {a->0.,b->10.}; vy {a->0.,b->0.}; x {a->0.,b->10.}; y {a->0.,b->10.} ] + emb W, B pre DiagB(a, b) and not ex x (W(x) and not ex y C(x, y)) RULE BlackStraight: [ | R:2 {}; W:1 {} | ] " @@ -68,20 +42,6 @@ B " emb W, B pre not ex x (W(x) and not ex y C(x, y)) -RULE BlackRight: - [ | W:1 {} | ] " - - ? B - - ?W ? -" -> [ | W:1 {} | - ] " - - ? . - - B ? -" emb W, B - pre not ex x (W(x) and not ex y C(x, y)) LOC 0 { PLAYER 1 PAYOFF { @@ -92,7 +52,7 @@ :(ex x (B(x) and not ex y C(y, x))) + -1. * :(ex x (W(x) and not ex y C(x, y))) } - MOVES [WhiteLeft -> 1]; [WhiteStraight -> 1]; [WhiteRight -> 1] + MOVES [WhiteDiag -> 1]; [WhiteStraight -> 1] } LOC 1 { PLAYER 2 @@ -104,7 +64,7 @@ :(ex x (B(x) and not ex y C(y, x))) + -1. * :(ex x (W(x) and not ex y C(x, y))) } - MOVES [BlackLeft -> 0]; [BlackStraight -> 0]; [BlackRight -> 0] + MOVES [BlackDiag -> 0]; [BlackStraight -> 0] } MODEL [ | | ] " Modified: trunk/Toss/examples/Chess.toss =================================================================== --- trunk/Toss/examples/Chess.toss 2010-12-19 20:42:04 UTC (rev 1262) +++ trunk/Toss/examples/Chess.toss 2010-12-19 22:43:09 UTC (rev 1263) @@ -1,5 +1,5 @@ PLAYERS 1, 2 -DATA depth: 1 +DATA depth: 0, adv_ratio: 1 REL IsFirst(x) = not ex z C(z, x) REL IsSecond(x) = ex y (C(y, x) and IsFirst(y)) REL IsEight(x) = not ex z C(x, z) Modified: trunk/Toss/examples/Gomoku.toss =================================================================== --- trunk/Toss/examples/Gomoku.toss 2010-12-19 20:42:04 UTC (rev 1262) +++ trunk/Toss/examples/Gomoku.toss 2010-12-19 22:43:09 UTC (rev 1263) @@ -1,5 +1,5 @@ PLAYERS 1, 2 -DATA r1: circle, r2: line, adv_ratio: 4 +DATA r1: circle, r2: line, adv_ratio: 4, depth: 1 RULE Cross: [a1 | P:1 {}; Q:1 {} | vx {a1->0.}; vy {a1->0.}; x {a1->0.}; y {a1->0.}] -> [a1 | P (a1); Q:1 {} | vx {a1->0.}; vy {a1->0.}; x {a1->0.}; y {a1->0.}] Modified: trunk/Toss/examples/Tic-Tac-Toe.toss =================================================================== --- trunk/Toss/examples/Tic-Tac-Toe.toss 2010-12-19 20:42:04 UTC (rev 1262) +++ trunk/Toss/examples/Tic-Tac-Toe.toss 2010-12-19 22:43:09 UTC (rev 1263) @@ -1,4 +1,5 @@ PLAYERS 1, 2 +DATA r1: circle, r2: line, adv_ratio: 4, depth: 3 REL WinQ() = ex x, y, z (Q(x) and Q(y) and Q(z) and ( This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-19 20:42:14
|
Revision: 1262 http://toss.svn.sourceforge.net/toss/?rev=1262&view=rev Author: lukstafi Date: 2010-12-19 20:42:04 +0000 (Sun, 19 Dec 2010) Log Message: ----------- Arena definition parsing bug fix. GDL parsing bug fix. Board elements <-> coordinates helpers. GDL test example: in progress. Modified Paths: -------------- trunk/Toss/Arena/Arena.ml trunk/Toss/Play/GDL.ml trunk/Toss/Play/GDL.mli trunk/Toss/Play/GDLParser.mly trunk/Toss/Play/GameTest.ml trunk/Toss/Play/Server.ml trunk/Toss/Play/ServerGDLTest.in trunk/Toss/Play/ServerGDLTest.out trunk/Toss/Solver/Structure.ml trunk/Toss/Solver/Structure.mli Modified: trunk/Toss/Arena/Arena.ml =================================================================== --- trunk/Toss/Arena/Arena.ml 2010-12-19 17:35:10 UTC (rev 1261) +++ trunk/Toss/Arena/Arena.ml 2010-12-19 20:42:04 UTC (rev 1262) @@ -154,7 +154,7 @@ (* Create a game state, possibly by extending an old state, from a list of definitions (usually corresponding to a ".toss" file.) *) let process_definition ?extend_state defs = - let (old_rules, old_locs, players, defined_rels, + let (old_rules, old_locs, players, old_defined_rels, state, time, cur_loc, data) = match extend_state with | None -> @@ -173,13 +173,10 @@ (List.length old_rules) (List.length old_locs); ); (* }}} *) - let rev_models_at_end l = - let m, n = List.partition (function StateStruc _ -> true | _ -> false) l in - n @ (List.rev m) in let rules, locations, players, defined_rels, state, time, cur_loc, data = - List.fold_right (fun def (rules, locations, players, defined_rels, - state, time, cur_loc, data) -> + List.fold_left (fun (rules, locations, players, defined_rels, + state, time, cur_loc, data) def -> match def with | DefRule (rname, r) -> ((rname, r)::rules, locations, players, defined_rels, @@ -206,14 +203,15 @@ | StateData more_data -> (rules, locations, players, defined_rels, state, time, cur_loc, data @ more_data) - ) (rev_models_at_end defs) ([], [], players, defined_rels, - state, time, cur_loc, data) in + ) ([], [], players, [], + state, time, cur_loc, data) defs in (* {{{ log entry *) if !debug_level > 2 then ( - printf "process_definition: %d new rules, %d defined rels\n%!" + printf "process_definition: %d new rules, %d new defined rels\n%!" (List.length rules) (List.length defined_rels); ); (* }}} *) + let defined_rels = old_defined_rels @ List.rev defined_rels in let def_rels_pure = List.map (fun (rel, args, body) -> (rel, (args, body))) defined_rels in let defined_rels = Modified: trunk/Toss/Play/GDL.ml =================================================================== --- trunk/Toss/Play/GDL.ml 2010-12-19 17:35:10 UTC (rev 1261) +++ trunk/Toss/Play/GDL.ml 2010-12-19 20:42:04 UTC (rev 1262) @@ -44,8 +44,22 @@ let client_player = ref (Const "uninitialized") let game_description = ref [] +let game_state = ref (ref Arena.empty_state) -let initialize_game player game_descr startcl = +let state_of_file s = + Printf.printf "GDL: Loading file %s...\n%!" s; + let f = open_in s in + let res = + ArenaParser.parse_game_state Lexer.lex + (Lexing.from_channel f) in + Printf.printf "GDL: File %s loaded.\n%!" s; + res + +let initialize_game state player game_descr startcl = + game_state := state; + + state := state_of_file "./examples/Tic-Tac-Toe.toss"; + client_player := player; game_description := game_descr; let effort, horizon, heur_adv_ratio = @@ -53,7 +67,20 @@ effort, horizon, heur_adv_ratio let translate_last_action actions = - "1", ["1","1"] + if actions = [] then + (* start of game -- Server will handle this answer as NOOP *) + "", [] + else + (* FIXME: really translate *) + "Cross", ["a1","a1"] -let translate_move move new_state = - "NOOP" +let translate_move rule emb new_state = + let struc = new_state.Arena.struc in + let elem = snd (List.hd emb) in + let c, r = + Structure.board_elem_coords (Structure.elem_str struc elem) in + let mark = Printf.sprintf "(MARK %d %d)" c r in + match rule with + | "Cross" -> "(" ^ mark ^ " NOOP)" + | "Circle" -> "(NOOP " ^ mark ^ ")" + | _ -> assert false Modified: trunk/Toss/Play/GDL.mli =================================================================== --- trunk/Toss/Play/GDL.mli 2010-12-19 17:35:10 UTC (rev 1261) +++ trunk/Toss/Play/GDL.mli 2010-12-19 20:42:04 UTC (rev 1262) @@ -41,11 +41,11 @@ game_descr_entry list -> game_description val initialize_game : - term -> game_description -> int -> int * int * float + Arena.game_state ref -> term -> game_description -> int -> int * int * float val translate_last_action : term list -> string * (string * string) list -(* FIXME: remove dependency on Game? *) +(* Rule name, embedding, game state. *) val translate_move : - Game.move -> Game.play_state -> string + string -> (int * int) list -> Arena.game_state -> string Modified: trunk/Toss/Play/GDLParser.mly =================================================================== --- trunk/Toss/Play/GDLParser.mly 2010-12-19 17:35:10 UTC (rev 1261) +++ trunk/Toss/Play/GDLParser.mly 2010-12-19 20:42:04 UTC (rev 1262) @@ -30,6 +30,9 @@ | Const c::args -> Func (c, args) | _ -> raise (Lexer.Parsing_error "GDL term: not a constant head") } +| error { + Lexer.report_parsing_error $startpos $endpos + "GDL: Syntax error in term." } atom: | r=WORD { Rel (r, []) } @@ -41,6 +44,9 @@ | Const r::args -> Rel (r, args) | _ -> raise (Lexer.Parsing_error "GDL atom: not a constant head") } +| error { + Lexer.report_parsing_error $startpos $endpos + "GDL: Syntax error in atom." } literal: | a=atom { Pos a } @@ -92,13 +98,17 @@ "GDL atomic entry: not init, role nor fact") } + %public game_description: - OPEN descr=list(game_descr_entry) CLOSE +| OPEN descr=list(game_descr_entry) CLOSE { compile_game_descr descr } +| error { + Lexer.report_parsing_error $startpos $endpos + "GDL: Syntax error in game description." } %public request: | OPEN start=WORD id=WORD role=term descr=game_description - startclock=WORD playclock=WORD + startclock=WORD playclock=WORD CLOSE { if start <> "START" && start <> "start" then raise (Lexer.Parsing_error "GDL request: start request expected") @@ -110,7 +120,8 @@ with Failure _ | Invalid_argument _ -> raise (Lexer.Parsing_error "GDL start: clock not a constant int") } -| OPEN command=WORD id=WORD actions=delimited (OPEN, list(term), CLOSE) +| OPEN command=WORD id=WORD + actions=delimited (OPEN, list(term), CLOSE) CLOSE { if command = "PLAY" || command = "play" then Play (id, actions) @@ -120,7 +131,7 @@ (Lexer.Parsing_error "GDL request: play or stop request expected") } -| OPEN command=WORD id=WORD actions=WORD +| OPEN command=WORD id=WORD actions=WORD CLOSE { if actions = "nil" || actions = "NIL" then ( if command = "PLAY" || command = "play" then @@ -132,6 +143,9 @@ ) else raise (Lexer.Parsing_error "GDL request: action list expected") } +| error { + Lexer.report_parsing_error $startpos $endpos + "GDL: Syntax error in request." } parse_game_description: | game_description EOF { $1 } Modified: trunk/Toss/Play/GameTest.ml =================================================================== --- trunk/Toss/Play/GameTest.ml 2010-12-19 17:35:10 UTC (rev 1261) +++ trunk/Toss/Play/GameTest.ml 2010-12-19 20:42:04 UTC (rev 1262) @@ -1205,11 +1205,11 @@ let a () = run_test_tt ~verbose:true experiments let a () = - Game.set_debug_level 3 + Server.set_debug_level 3 let a () = match test_filter - ["Game:0:misc:5:chess draw"] + ["Game:0:misc:1:server: ServerGDLTest.in GDL Tic-Tac-Toe"] tests with | Some tests -> ignore (run_test_tt ~verbose:true tests) Modified: trunk/Toss/Play/Server.ml =================================================================== --- trunk/Toss/Play/Server.ml 2010-12-19 17:35:10 UTC (rev 1261) +++ trunk/Toss/Play/Server.ml 2010-12-19 20:42:04 UTC (rev 1262) @@ -55,9 +55,15 @@ let req_of_str s = let s_len = String.length s in if s_len > 4 && String.sub s 0 4 = "GDL " - then + then ( + (* {{{ log entry *) + if !debug_level > 1 then ( + Printf.printf "req_of_str-GDL:\n%s\n%!" (String.sub s 4 (s_len-4)); + ); + (* }}} *) Aux.Right (GDLParser.parse_request KIFLexer.lex (Lexing.from_string (String.sub s 4 (s_len-4)))) + ) else Aux.Left (ArenaParser.parse_request Lexer.lex (Lexing.from_string s)) @@ -258,7 +264,7 @@ | Aux.Right (GDL.Start (_, player, game_descr, startcl, playcl)) -> (* GDL will store the player and the game in its state. *) let effort, horizon, heur_adv_ratio = - GDL.initialize_game player game_descr startcl in + GDL.initialize_game state player game_descr startcl in (* TODO: handle timer (startclock) in Game.initialize_default*) let p, ps = Game.initialize_default !state ~effort ~search_method:"alpha_beta_ord" @@ -275,6 +281,7 @@ let r_name, mtch = GDL.translate_last_action actions in + if r_name <> "" then ( let {Arena.rules=rules; graph=graph} = !state.Arena.game in let struc = !state.Arena.struc in let fn s n = Structure.find_elem s n in @@ -291,6 +298,12 @@ for i = 0 to Array.length moves - 1 do (* FIXME: handle time and params! *) let mov = moves.(i) in + (* {{{ log entry *) + if !debug_level > 1 then ( + Printf.printf "GDL: considering move %s\n%!" + (Game.move_gs_str !state mov) + ); + (* }}} *) if r_name = mov.Game.rule && (* t = mov.Game.time && *) @@ -309,6 +322,7 @@ done; (* TODO: if not due to only time or params mismatch, block or warn about invalid rule application *) + failwith "Server GDL Play request: action mismatched with play state" with Found pos -> pos) in @@ -333,8 +347,8 @@ play_state := Some { Game.game_state = new_game_state; memory = memory; - }; - + }); + let time_used = time_started - (int_of_float (ceil (Sys.time ()))) in let p, ps = @@ -349,7 +363,8 @@ match res with | Some (move, new_state) -> play_state := Some new_state; - GDL.translate_move move new_state + GDL.translate_move move.Game.rule move.Game.embedding + !state | None -> "NOOP" in let msg_len = String.length mov_msg in "HTTP/1.0 200 OK\r\nContent-type: text/acl\r\nContent-length: " Modified: trunk/Toss/Play/ServerGDLTest.in =================================================================== --- trunk/Toss/Play/ServerGDLTest.in 2010-12-19 17:35:10 UTC (rev 1261) +++ trunk/Toss/Play/ServerGDLTest.in 2010-12-19 20:42:04 UTC (rev 1262) @@ -3,9 +3,9 @@ Sender: GAMEMASTER Receiver: GAMEPLAYER Content-type: text/acl -Content-length: 1587 +Content-length: 1589 -(START MATCH.3316980891 X (ROLE X) (ROLE O) (INIT (CELL 1 1 B)) (INIT (CELL 1 2 B)) (INIT (CELL 1 3 B)) (INIT (CELL 2 1 B)) (INIT (CELL 2 2 B)) (INIT (CELL 2 3 B)) (INIT (CELL 3 1 B)) (INIT (CELL 3 2 B)) (INIT (CELL 3 3 B)) (INIT (CONTROL X)) (<= (NEXT (CELL ?X ?Y ?PLAYER)) (DOES ?PLAYER (MARK ?X ?Y))) (<= (NEXT (CELL ?X ?Y ?MARK)) (TRUE (CELL ?X ?Y ?MARK)) (DOES ?PLAYER (MARK ?M ?N)) (DISTINCTCELL ?X ?Y ?M ?N)) (<= (NEXT (CONTROL X)) (TRUE (CONTROL O))) (<= (NEXT (CONTROL O)) (TRUE (CONTROL X))) (<= (ROW ?X ?PLAYER) (TRUE (CELL ?X 1 ?PLAYER)) (TRUE (CELL ?X 2 ?PLAYER)) (TRUE (CELL ?X 3 ?PLAYER))) (<= (COLUMN ?Y ?PLAYER) (TRUE (CELL 1 ?Y ?PLAYER)) (TRUE (CELL 2 ?Y ?PLAYER)) (TRUE (CELL 3 ?Y ?PLAYER))) (<= (DIAGONAL ?PLAYER) (TRUE (CELL 1 1 ?PLAYER)) (TRUE (CELL 2 2 ?PLAYER)) (TRUE (CELL 3 3 ?PLAYER))) (<= (DIAGONAL ?PLAYER) (TRUE (CELL 1 3 ?PLAYER)) (TRUE (CELL 2 2 ?PLAYER)) (TRUE (CELL 3 1 ?PLAYER))) (<= (LINE ?PLAYER) (ROW ?X ?PLAYER)) (<= (LINE ?PLAYER) (COLUMN ?Y ?PLAYER)) (<= (LINE ?PLAYER) (DIAGONAL ?PLAYER)) (<= OPEN (TRUE (CELL ?X ?Y B))) (<= (DISTINCTCELL ?X ?Y ?M ?N) (DISTINCT ?X ?M)) (<= (DISTINCTCELL ?X ?Y ?M ?N) (DISTINCT ?Y ?N)) (<= (LEGAL ?PLAYER (MARK ?X ?Y)) (TRUE (CELL ?X ?Y B)) (TRUE (CONTROL ?PLAYER))) (<= (LEGAL ?PLAYER NOOP) (NOT (TRUE (CONTROL ?PLAYER)))) (<= (GOAL ?PLAYER 100) (LINE ?PLAYER)) (<= (GOAL ?PLAYER 50) (NOT (LINE X)) (NOT (LINE O)) (NOT OPEN)) (<= (GOAL ?PLAYER1 0) (LINE ?PLAYER2) (DISTINCT ?PLAYER1 ?PLAYER2)) (<= (GOAL ?PLAYER 0) (NOT (LINE X)) (NOT (LINE O)) OPEN) (<= TERMINAL (LINE ?PLAYER)) (<= TERMINAL (NOT OPEN)) 30 30) +(START MATCH.3316980891 X ((ROLE X) (ROLE O) (INIT (CELL 1 1 B)) (INIT (CELL 1 2 B)) (INIT (CELL 1 3 B)) (INIT (CELL 2 1 B)) (INIT (CELL 2 2 B)) (INIT (CELL 2 3 B)) (INIT (CELL 3 1 B)) (INIT (CELL 3 2 B)) (INIT (CELL 3 3 B)) (INIT (CONTROL X)) (<= (NEXT (CELL ?X ?Y ?PLAYER)) (DOES ?PLAYER (MARK ?X ?Y))) (<= (NEXT (CELL ?X ?Y ?MARK)) (TRUE (CELL ?X ?Y ?MARK)) (DOES ?PLAYER (MARK ?M ?N)) (DISTINCTCELL ?X ?Y ?M ?N)) (<= (NEXT (CONTROL X)) (TRUE (CONTROL O))) (<= (NEXT (CONTROL O)) (TRUE (CONTROL X))) (<= (ROW ?X ?PLAYER) (TRUE (CELL ?X 1 ?PLAYER)) (TRUE (CELL ?X 2 ?PLAYER)) (TRUE (CELL ?X 3 ?PLAYER))) (<= (COLUMN ?Y ?PLAYER) (TRUE (CELL 1 ?Y ?PLAYER)) (TRUE (CELL 2 ?Y ?PLAYER)) (TRUE (CELL 3 ?Y ?PLAYER))) (<= (DIAGONAL ?PLAYER) (TRUE (CELL 1 1 ?PLAYER)) (TRUE (CELL 2 2 ?PLAYER)) (TRUE (CELL 3 3 ?PLAYER))) (<= (DIAGONAL ?PLAYER) (TRUE (CELL 1 3 ?PLAYER)) (TRUE (CELL 2 2 ?PLAYER)) (TRUE (CELL 3 1 ?PLAYER))) (<= (LINE ?PLAYER) (ROW ?X ?PLAYER)) (<= (LINE ?PLAYER) (COLUMN ?Y ?PLAYER)) (<= (LINE ?PLAYER) (DIAGONAL ?PLAYER)) (<= OPEN (TRUE (CELL ?X ?Y B))) (<= (DISTINCTCELL ?X ?Y ?M ?N) (DISTINCT ?X ?M)) (<= (DISTINCTCELL ?X ?Y ?M ?N) (DISTINCT ?Y ?N)) (<= (LEGAL ?PLAYER (MARK ?X ?Y)) (TRUE (CELL ?X ?Y B)) (TRUE (CONTROL ?PLAYER))) (<= (LEGAL ?PLAYER NOOP) (NOT (TRUE (CONTROL ?PLAYER)))) (<= (GOAL ?PLAYER 100) (LINE ?PLAYER)) (<= (GOAL ?PLAYER 50) (NOT (LINE X)) (NOT (LINE O)) (NOT OPEN)) (<= (GOAL ?PLAYER1 0) (LINE ?PLAYER2) (DISTINCT ?PLAYER1 ?PLAYER2)) (<= (GOAL ?PLAYER 0) (NOT (LINE X)) (NOT (LINE O)) OPEN) (<= TERMINAL (LINE ?PLAYER)) (<= TERMINAL (NOT OPEN))) 30 30) POST / HTTP/1.0 Accept: text/delim @@ -23,7 +23,7 @@ Content-type: text/acl Content-length: 41 -(PLAY MATCH.3316980891 ((MARK 3 3) NOOP)) +(PLAY MATCH.3316980891 ((MARK 2 2) NOOP)) POST / HTTP/1.0 Accept: text/delim @@ -32,7 +32,7 @@ Content-type: text/acl Content-length: 41 -(PLAY MATCH.3316980891 (NOOP (MARK 1 3))) +(PLAY MATCH.3316980891 (NOOP (MARK 1 1))) POST / HTTP/1.0 Accept: text/delim Modified: trunk/Toss/Play/ServerGDLTest.out =================================================================== --- trunk/Toss/Play/ServerGDLTest.out 2010-12-19 17:35:10 UTC (rev 1261) +++ trunk/Toss/Play/ServerGDLTest.out 2010-12-19 20:42:04 UTC (rev 1262) @@ -7,7 +7,7 @@ Content-type: text/acl Content-length: 10 -(MARK 3 3) +(MARK 2 2) HTTP/1.0 200 OK Content-type: text/acl Content-length: 4 Modified: trunk/Toss/Solver/Structure.ml =================================================================== --- trunk/Toss/Solver/Structure.ml 2010-12-19 17:35:10 UTC (rev 1261) +++ trunk/Toss/Solver/Structure.ml 2010-12-19 20:42:04 UTC (rev 1262) @@ -1033,6 +1033,19 @@ Format.fprintf Format.str_formatter "%a" fprint struc; Format.flush_str_formatter () +let board_elem_coords name = + let col_index = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" in + let col = String.index col_index name.[0] + 1 in + try col, int_of_string (String.sub name 1 (String.length name - 1)) + with Failure _ | Invalid_argument _ -> + raise Not_found + +let board_coords_name (col, row) = + if col < 1 || col > 52 || row < 1 then raise Not_found; + let col_index = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" in + Char.escaped col_index.[col-1] ^ string_of_int row (* -------------------- PARSER HELPERS -------------------- *) Modified: trunk/Toss/Solver/Structure.mli =================================================================== --- trunk/Toss/Solver/Structure.mli 2010-12-19 17:35:10 UTC (rev 1261) +++ trunk/Toss/Solver/Structure.mli 2010-12-19 20:42:04 UTC (rev 1262) @@ -105,7 +105,14 @@ val sprint : structure -> string +(** Coordinates, column first, of a board element name. Raises + [Not_found] if the name is not of proper format. *) +val board_elem_coords : string -> int * int +(** Board element name under given coordinates, column first. Raises + [Not_found] if the coordinates are out of bounds. *) +val board_coords_name : int * int -> string + (** {2 Adding elements possibly with string names} *) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-19 17:35:17
|
Revision: 1261 http://toss.svn.sourceforge.net/toss/?rev=1261&view=rev Author: lukaszkaiser Date: 2010-12-19 17:35:10 +0000 (Sun, 19 Dec 2010) Log Message: ----------- Corrections to WebClient. Modified Paths: -------------- trunk/Toss/WebClient/Connect.js trunk/Toss/WebClient/DefaultStyle.js trunk/Toss/WebClient/Handler.py trunk/Toss/WebClient/Login.js trunk/Toss/WebClient/Main.js trunk/Toss/WebClient/README trunk/Toss/WebClient/Style.css trunk/Toss/WebClient/index.html Added Paths: ----------- trunk/Toss/WebClient/MakeDB.py Removed Paths: ------------- trunk/Toss/WebClient/make_db.py Modified: trunk/Toss/WebClient/Connect.js =================================================================== --- trunk/Toss/WebClient/Connect.js 2010-12-19 14:31:15 UTC (rev 1260) +++ trunk/Toss/WebClient/Connect.js 2010-12-19 17:35:10 UTC (rev 1261) @@ -12,8 +12,6 @@ var SVG_HEIGHT = 500; var SVG_MARGINX = 50; var SVG_MARGINY = 50; -var VIEW_WIDTH = "20em"; -var VIEW_HEIGHT = "20em"; var VIEW_MIRROR = 0; var GAME_NAME = ""; // name of current game, e.g. "Breakthrough" @@ -65,7 +63,7 @@ // Send [msg] to server and return response text. function sync_server_msg (msg) { var xml_request = new XMLHttpRequest (); - xml_request.open ('POST', 'TossHandler.py', false); + xml_request.open ('POST', 'Handler.py', false); xml_request.setRequestHeader ('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); xml_request.send (msg); @@ -77,11 +75,33 @@ return (resp) } +// Send [msg] to server asynchronously, ignore response text. +function async_server_msg (msg) { + var xml_request = new XMLHttpRequest (); + xml_request.open ('POST', 'Handler.py', true); + xml_request.setRequestHeader ('Content-Type', + 'application/x-www-form-urlencoded; charset=UTF-8'); + xml_request.onreadystatechange = function () { + if (xml_request.readyState == 4) { + resp = xml_request.responseText; + if (resp.indexOf ("MOD_PYTHON ERROR") > -1) { + alert (resp.substring(resp.indexOf("Traceback"))); + } + } + }; + xml_request.send (msg); +} + // Send [msg] to server attaching prefix '[cmd]#' and return response text. function srv (cmd, msg) { return (sync_server_msg (cmd + '#' + msg)); } +// Send [msg] to server attaching prefix '[cmd]#' async., ignore response. +function async_srv (cmd, msg) { + return (async_server_msg (cmd + '#' + msg)); +} + // Strip [c1] and [c2] from beginning and end of [str]. function strip (c1, c2, str) { if (str.length == 0) return (str); @@ -172,15 +192,11 @@ // ---- Two functions below are very basic and thus in this file. --- // Create basic svg box. -function create_svg_box (bwidth, bheight, margx, margy, parent_id) { - VIEW_WIDTH = bwidth; - VIEW_HEIGHT = bheight; +function create_svg_box (margx, margy, parent_id) { SVG_MARGINX = margx; SVG_MARGINY = margx; var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svg.setAttribute('id', 'svg'); - svg.setAttribute('width', bwidth); - svg.setAttribute('height', bheight); var wx = SVG_WIDTH + 2*SVG_MARGINX; var wy = SVG_HEIGHT + 2*SVG_MARGINY; svg.setAttribute('viewBox', '0 0 ' + wx + " " + wy); Modified: trunk/Toss/WebClient/DefaultStyle.js =================================================================== --- trunk/Toss/WebClient/DefaultStyle.js 2010-12-19 14:31:15 UTC (rev 1260) +++ trunk/Toss/WebClient/DefaultStyle.js 2010-12-19 17:35:10 UTC (rev 1261) @@ -2,7 +2,6 @@ // This module implements default drawing style for games. // Functions expected from this module: -// - draw_outline () // - draw_elem (elem) // - highlight_elem (elem) // - unhighlight_elem (elem) @@ -136,12 +135,6 @@ class="chess-path-D" /> \ </g>'; -// Draw a box around the board. -function draw_outline () { - var w = SVG_WIDTH + 2*SVG_MARGINX; - var h = SVG_HEIGHT + 2*SVG_MARGINY; - add_svg ("rect", [["class", "board-outline"], ["width", w], ["height", h]]); -} // Draw the element [elem]. function draw_elem (elem) { Modified: trunk/Toss/WebClient/Handler.py =================================================================== --- trunk/Toss/WebClient/Handler.py 2010-12-19 14:31:15 UTC (rev 1260) +++ trunk/Toss/WebClient/Handler.py 2010-12-19 17:35:10 UTC (rev 1261) @@ -1,14 +1,12 @@ import subprocess import socket import time -from Wrapper import * from mod_python import apache, Cookie from pysqlite2 import dbapi2 as sqlite3 +from Wrapper import * +import MakeDB -DB_FILE = "/var/www/WebClient/tossdb.sqlite" -TUID = "toss_id_05174_" - def tmp_log (str): file = open ("/tmp/th.log", 'a') file.write (str) @@ -21,7 +19,7 @@ return (res) def open_toss_server (port): - args = ["/var/www/WebClient/TossServer", + args = [MakeDB.SERVER_FILE, "-s", "localhost", "-p", str(port)] server_proc = subprocess.Popen(args) time.sleep (0.1) @@ -30,7 +28,7 @@ def get_global_lock (db): cur = db.cursor () cur.execute ("update lock set locked='true' " + - " where locked='false' and tid='" + str(TUID) + "'") + " where locked='false' and tid='" + str(MakeDB.TUID) + "'") db.commit () if cur.rowcount == 1: return @@ -39,7 +37,7 @@ def release_global_lock (db): db.execute ("update lock set locked='false' " + - " where locked='true' and tid='" + str(TUID) + "'") + " where locked='true' and tid='" + str(MakeDB.TUID) + "'") db.commit () def get_toss_port (db): @@ -160,10 +158,10 @@ def confirm_username (db, req): cookies = Cookie.get_cookies(req) - if not (cookies.has_key(TUID + 'username')): return "" - if not (cookies.has_key(TUID + 'passphrase')): return "" - uid = cookies[TUID + 'username'].value - pwd1 = cookies[TUID + 'passphrase'].value + if not (cookies.has_key(MakeDB.TUID + 'username')): return "" + if not (cookies.has_key(MakeDB.TUID + 'passphrase')): return "" + uid = cookies[MakeDB.TUID + 'username'].value + pwd1 = cookies[MakeDB.TUID + 'passphrase'].value pwd2 = passwd_from_db (db, uid) if (pwd1 != pwd2): return "" return (uid) @@ -174,11 +172,11 @@ if (pwd != db_pwd): return ("wrong password") t = time.time() + 3600000; if chk == "false": - cookie1 = Cookie.Cookie(TUID + 'username', uid) - cookie2 = Cookie.Cookie(TUID + 'passphrase', pwd) + cookie1 = Cookie.Cookie(MakeDB.TUID + 'username', uid) + cookie2 = Cookie.Cookie(MakeDB.TUID + 'passphrase', pwd) else: - cookie1 = Cookie.Cookie(TUID + 'username', uid, expires=t) - cookie2 = Cookie.Cookie(TUID + 'passphrase', pwd, expires=t) + cookie1 = Cookie.Cookie(MakeDB.TUID + 'username', uid, expires=t) + cookie2 = Cookie.Cookie(MakeDB.TUID + 'passphrase', pwd, expires=t) Cookie.add_cookie(req, cookie1) Cookie.add_cookie(req, cookie2) return ("OK") @@ -231,9 +229,16 @@ db.commit () return ("OK") +def user_plays (db, usr): + name = get_user_name (db, usr); + plays = "" + for g in MakeDB.GAMES: + plays += "$" + list_plays (db, g, usr) + return (usr + "$" + name + plays) + def handler(req): req.content_type = "text/plain" - db = sqlite3.connect(DB_FILE) + db = sqlite3.connect(MakeDB.DB_FILE) usr = confirm_username (db, req) msg = req.read () #tmp_log(msg) @@ -241,6 +246,12 @@ if cmd == "USERNAME": req.write(usr) return apache.OK + if cmd == "USERPLAYS": + if usr == "": + req.write(usr) + return apache.OK + req.write (user_plays (db, usr)) + return apache.OK if cmd == "REGISTER": ui = data.split('$') if register_user (db, ui): @@ -260,8 +271,8 @@ req.write("Login failed for " + ui[0] + ": " + res) return apache.OK if cmd == "LOGOUT": - cookie1 = Cookie.Cookie(TUID + 'passphrase', "a") - cookie2 = Cookie.Cookie(TUID + 'username', "a") + cookie1 = Cookie.Cookie(MakeDB.TUID + 'passphrase', "a") + cookie2 = Cookie.Cookie(MakeDB.TUID + 'username', "a") Cookie.add_cookie(req, cookie1) Cookie.add_cookie(req, cookie2) req.write ("User logged out: " + usr + ".") Modified: trunk/Toss/WebClient/Login.js =================================================================== --- trunk/Toss/WebClient/Login.js 2010-12-19 14:31:15 UTC (rev 1260) +++ trunk/Toss/WebClient/Login.js 2010-12-19 17:35:10 UTC (rev 1261) @@ -12,19 +12,21 @@ } // Setup a user -function setup_user (un) { - UNAME = un - document.getElementById("topuser").innerHTML = "Welcome " + disp_name(un); +function setup_user (udata) { + UNAME = udata[0]; + UNAME_TO_NAME_MAP[UNAME] = udata[1]; + document.getElementById("topuser").innerHTML = + "Welcome " + disp_name(UNAME); document.getElementById("loginform").style.display = "none"; document.getElementById("topright-register").style.display = "none"; document.getElementById("topright").style.display = "inline"; document.getElementById("welcome").style.display = "none"; document.getElementById("plays").style.display = "block"; - list_plays ("Breakthrough"); - list_plays ("Chess"); - list_plays ("Entanglement"); - list_plays ("Gomoku"); - list_plays ("Tic-Tac-Toe"); + list_plays_string ("Breakthrough", udata[2]); + list_plays_string ("Chess", udata[3]); + list_plays_string ("Entanglement", udata[4]); + list_plays_string ("Gomoku", udata[5]); + list_plays_string ("Tic-Tac-Toe", udata[6]); get_opponents (); } @@ -45,8 +47,8 @@ if (navigator.userAgent.indexOf('MSIE') !=-1) { document.getElementById("nosvg").style.display = "block"; } else { - var un = srv("USERNAME", "user"); - if (un != "") { setup_user (un) }; + var udata = srv("USERPLAYS", "user"); + if (udata != "") { setup_user (udata.split("$")) }; } } Modified: trunk/Toss/WebClient/Main.js =================================================================== --- trunk/Toss/WebClient/Main.js 2010-12-19 14:31:15 UTC (rev 1260) +++ trunk/Toss/WebClient/Main.js 2010-12-19 17:35:10 UTC (rev 1261) @@ -34,7 +34,6 @@ // Draw the model using function from Toss[X]Style.js. // WARNING: must call get_model_info first! function draw_model () { - draw_outline (); for (var i = 0; i < ELEMS.length; i++) { draw_elem (ELEMS[i]); } @@ -59,7 +58,7 @@ clear_svg (); document.getElementById("working").style.display = "block"; get_model_info (); - create_svg_box (VIEW_WIDTH, VIEW_HEIGHT, SVG_MARGINX, SVG_MARGINY, "board"); + create_svg_box (SVG_MARGINX, SVG_MARGINY, "board"); draw_model (); document.getElementById("working").style.display = "none"; } @@ -127,17 +126,17 @@ li.setAttribute ("class", "plays-list-elem"); li.setAttribute ("id", "plays-list-" + game + "-elem-" + i); var p = PLAYS[i][2]; - var bs = '<button class="bt" title="Open" onclick="'+ "play_click('" + - game + "', " + p + ", " + i + ')">Open</button> '; - li.innerHTML = bs + disp_name(PLAYS[i][0]) +" vs " + - disp_name(PLAYS[i][1])+ " (game " + PLAYS[i][2] + ')' - + var pname = disp_name(PLAYS[i][0]) +" vs " + disp_name(PLAYS[i][1]) + + " (game " + PLAYS[i][2] + ')'; + var bs = '<button class="obt" title="Open game ' + PLAYS[i][2] + + '" onclick="'+ "play_click('" + game + "', " + p + ", " + i + ')">' + + pname + '</button> '; + li.innerHTML = bs // +'<a href="#" onclick="'+ "del_play('"+ fn + "')" + '">Delete</a>'; return (li); } -function list_plays (game) { - var lst = srv ("LIST_PLAYS", "'" + game + "', '" + UNAME + "'"); +function list_plays_string (game, lst) { PLAYS = convert_python_list (',', lst); var plist = document.getElementById("plays-list-" + game); while (plist.childNodes.length > 0) { plist.removeChild(plist.firstChild); } @@ -154,18 +153,22 @@ } } +function list_plays (game) { + var lst = srv ("LIST_PLAYS", "'" + game + "', '" + UNAME + "'"); + list_plays_string (game, lst); +} + + function game_click (game) { document.getElementById("welcome").style.display = "none"; document.getElementById("game-disp").style.display = "none"; document.getElementById("plays").style.display = "none"; GAME_NAME = game; if (game == "Tic-Tac-Toe") { // bigger margins needed - create_svg_box ("19em", "19em", 130, 130, "board"); + create_svg_box (130, 130, "board"); } else { - create_svg_box ("19em", "19em", 40, 40, "board"); + create_svg_box (40, 40, "board"); } - document.getElementById("opening").style.display = "block"; - document.getElementById("opening").style.display = "none"; document.getElementById("game-disp").style.display = "block"; } @@ -192,6 +195,7 @@ alert ("It is your Opponent's turn"); return; } + document.getElementById("working").style.display = "block"; var info = srv("MOVE_PLAY", 'c, '+ CUR_MOVE +', '+ play_py_id (CUR_PLAY_I)); set_info (info); clear_move_cache (); @@ -201,9 +205,10 @@ document.getElementById("cur-player").innerHTML = disp_name(PLAYS[CUR_PLAY_I][(m + 1) % 2]); document.getElementById('cur-move').innerHTML = "none"; + document.getElementById("working").style.display = "none"; full_redraw (); PLAYS[CUR_PLAY_I][3] = parseInt(PLAYS[CUR_PLAY_I][3]) + 1; - srv ("UPD_SVG", play_py_id(CUR_PLAY_I) + ", " + svg_string()); + async_srv ("UPD_SVG", play_py_id(CUR_PLAY_I) + ", " + svg_string()); var old_li = document.getElementById ("plays-list-" + GAME_NAME + "-elem-" + CUR_PLAY_I); var li = new_play_item (GAME_NAME, CUR_PLAY_I); old_li.parentNode.replaceChild (li, old_li); @@ -300,14 +305,17 @@ function new_play_do (opp_uid) { list_plays (GAME_NAME) game_click (GAME_NAME) + document.getElementById ("game-title").innerHTML = GAME_NAME; document.getElementById("opponents").style.display = "none"; var olist = document.getElementById("opponents-list"); while (olist.childNodes.length > 0) { olist.removeChild(olist.firstChild); } if (opp_uid == -1) { opp_uid = UNAME; } if (opp_uid == 0 || UNAME == "") { return; } document.getElementById("plays-list-" + GAME_NAME).style.display = "block"; + document.getElementById("working").style.display = "block"; info_nbr = srv ("NEW_PLAY", "c, '" + GAME_NAME + "', '" + UNAME + "', '" + opp_uid + "', 0"); + document.getElementById("working").style.display = "none"; info_idx = info_nbr.indexOf('$'); FREE_PLAY_NO = parseInt(info_nbr.substring(0, info_idx)); document.getElementById("play-number").innerHTML = "" + FREE_PLAY_NO; @@ -320,7 +328,7 @@ PLAYS.push(p); set_info(info_nbr.substring(info_idx+1)); full_redraw (); - srv ("UPD_SVG", play_py_id(CUR_PLAY_I) + ", " + svg_string()); + async_srv ("UPD_SVG", play_py_id(CUR_PLAY_I) + ", " + svg_string()); li = new_play_item (GAME_NAME, CUR_PLAY_I); document.getElementById("plays-list-" + GAME_NAME).appendChild(li); } @@ -328,4 +336,4 @@ function get_opponents () { var lst = srv ("LIST_FRIENDS", "user"); FRIENDS = convert_python_list (',', lst); -} \ No newline at end of file +} Copied: trunk/Toss/WebClient/MakeDB.py (from rev 1258, trunk/Toss/WebClient/make_db.py) =================================================================== --- trunk/Toss/WebClient/MakeDB.py (rev 0) +++ trunk/Toss/WebClient/MakeDB.py 2010-12-19 17:35:10 UTC (rev 1261) @@ -0,0 +1,47 @@ +#!/usr/bin/python + +import os +from pysqlite2 import dbapi2 as sqlite3 + +DB_FILE = "/var/www/WebClient/tossdb.sqlite" + +SERVER_FILE = "/var/www/WebClient/TossServer" + +GAMES_PATH = "../examples" +GAMES = ["Breakthrough", "Chess", "Entanglement", "Gomoku", "Tic-Tac-Toe"] + +TUID = "toss_id_05174_" + + + +def create_db (db_file, games_path, games): + conn = sqlite3.connect(db_file) + conn.execute("create table users(id string primary key," + + " name string, surname string, email string, passwd string)") + conn.execute("create table cur_states(playid int primary key," + + " game string, player1 string, player2 string," + + " move int, toss string, info string, svg string)") + conn.execute("create table old_states(playid int," + + " game string, player1 string, player2 string," + + " move int, toss string, info string, svg string)") + conn.execute("create table games(game string primary key, toss string)") + conn.execute("create table ports(port int primary key, locked bool)") + conn.execute("create table lock(tid int primary key, locked bool)") + conn.execute("create table friends(id string, fid string)") + conn.commit () + conn.execute ("insert into lock(tid, locked) values (?, ?)", + (TUID, 'false')) + for g in games: + f = open(games_path + "/" + g + ".toss") + toss = f.read() + f.close() + conn.execute ("insert into games(game, toss) values (?, ?)", (g, toss)) + print ("Added " + g) + conn.commit () + os.chmod (db_file, 0777) + + +if __name__ == "__main__": + print "Creating empty Toss DB" + create_db (DB_FILE, GAMES_PATH, GAMES) + print "Created tossdb.sqlite" Modified: trunk/Toss/WebClient/README =================================================================== --- trunk/Toss/WebClient/README 2010-12-19 14:31:15 UTC (rev 1260) +++ trunk/Toss/WebClient/README 2010-12-19 17:35:10 UTC (rev 1261) @@ -21,7 +21,6 @@ TODO: - move interface: first click all, second click toggle, if one - confirm msg - move suggestions and play against computer - - after the above: show game result in the middle / instead of move - sort plays by who's turn it is - option to give up game and offer a draw - enable google (or other) analytics Modified: trunk/Toss/WebClient/Style.css =================================================================== --- trunk/Toss/WebClient/Style.css 2010-12-19 14:31:15 UTC (rev 1260) +++ trunk/Toss/WebClient/Style.css 2010-12-19 17:35:10 UTC (rev 1261) @@ -1,14 +1,20 @@ /* General */ html { + position: absolute; height: 100%; width: 100%; } body { + position: absolute; + height: 100%; + width: 100%; + padding: 0px; + margin: 0px; + text-align: center; background-color: #b5bf8f; font-family: Verdana, 'TeXGyreHerosRegular', sans; - height: 100%; } .bt { @@ -30,9 +36,26 @@ #plays .bt { width: 7em; position: absolute; - right: 0px; + right: 2px; } +.obt { + text-align: left; + border-color: #260314; + border-radius: 4px; + -moz-border-radius: 4px; + border-width: 0px; + color: #260314; + background-color: #ffe4aa; + font-size: 0.9em; + font-family: Verdana, 'TeXGyreHerosRegular', sans; +} + +.obt:hover { + cursor: pointer; + text-decoration: underline; +} + .dbt { border-color: #ffe4aa; border-radius: 4px; @@ -142,26 +165,25 @@ #login1 { position: absolute; top: 0px; - left: 10em; + left: 8em; } #login2 { position: absolute; top: 0px; - left: 20em; + left: 18em; } #login3 { position: absolute; top: 0.3em; - left: 30em; + left: 28em; } #logo { font-size: 2em; float: left; font-family: arial, 'OFLSortsMillGoudyRegular', serif; - width: 4.5em; padding-left: 0.25em; } @@ -192,10 +214,12 @@ border-color: #260314; border-style: solid; border-width: 0px 0px 5px 0px; + z-index: 9; + text-align: left; } #topbar { - margin-left: 9.5em; + margin-left: 6.5em; padding-left: 1em; padding-right: 1em; padding-top: 0.7em; @@ -217,11 +241,12 @@ } #bottom { - position: relative; + position: absolute; bottom: 0px; - left: -0.5em; + left: 0em; width: 100%; - padding-right: 1em; + padding: 0px; + margin: 0px; height: 1.3em; text-align: right; color: #ffe4aa; @@ -266,16 +291,24 @@ } #main { - margin-top: 2.5em; + text-align: left; + position: absolute; + top: 0px; + bottom: 0px; + left: 0px; + right: 0px; + margin-left: auto; + margin-right: auto; + width: 90%; + height: 100%; + padding-top: 0px; + padding-bottom: 0px; + padding-left: 2px; + padding-right: 2px; color: #260314; background-color: #ffe4aa; - margin-left: 1em; - margin-right: 1em; - padding: 1em; - min-height: 100%; - padding-bottom: 2em; - border: 1px solid #260314; - border-bottom: 0px; + border-left: 1px solid #260314; + border-right: 1px solid #260314; } #main a, #main a:link, #main a:active, #main a:visited { @@ -360,10 +393,13 @@ } #game-disp { - position: relative; - top: -1em; - left: 0em; - width: 30em; + text-align: center; + margin-left: auto; + margin-right: auto; + margin-top: 3em; + min-width: 10em; + max-width: 60em; + width: 80%; display: none; } @@ -379,29 +415,24 @@ padding: 0px; } -#game-desc { - text-align: justify; - display: none; - width: 29em; - height: 19em; - margin-right: 1em; - padding-right: 1em; - border-right: 1px solid #260314; -} - #board { - position: absolute; - left: 0em; - top: 3.5em; - width: 20em; - height: 20em; + min-width: 10em; + max-width: 60em; + width: 70%; + margin-left: auto; + margin-right: auto; + margin-top: 0em; + text-align: center; } #working { position: absolute; - left: 4.5em; + left: 0px; + right: 0px; top: 7em; width: 10em; + margin-left: auto; + margin-right: auto; text-align: center; font-weight: bold; color: #ffe4aa; @@ -429,15 +460,19 @@ } .game-par { - padding-top: 2px; - border-top: 2px solid #260314; + padding: 0px; + border-top: 0px solid #260314; } #plays { position: absolute; - top: 3em; - left: 3em; - width: 30em; + left: 0px; + right: 0px; + top: 2.5em; + margin-left: auto; + margin-right: auto; + width: 100%; + max-width: 50em; display: none; } @@ -445,12 +480,12 @@ margin-left: 1em; padding-left: 0px; list-style: none; - margin-top: 0.25em; + margin-top: 0em; } .plays-list-elem { margin-left: 0em; - margin-bottom: 0.5em; + margin-bottom: 0em; } .plays-list-elem a { @@ -467,10 +502,14 @@ /* SVG styling */ -.board-outline { - fill: #b5bf8f; - stroke: #260314; - stroke-width: 10px; +#svg { + min-width: 10em; + max-width: 60em; + width: 70%; + min-height: 10em; + max-height: 60em; + height: 70%; + /* border: 1px solid #260314; */ } .model-elem { @@ -527,139 +566,139 @@ } .chessW .chess-path-A { - opacity:1; - fill:#ffe4aa; - fill-opacity:1; - fill-rule:nonzero; - stroke:#260314; - stroke-width:1.5; - stroke-linecap:round; - stroke-linejoin:miter; - stroke-miterlimit:4; - stroke-dasharray:none; - stroke-dashoffset:10; - stroke-opacity:1; + opacity: 1; + fill: #ffe4aa; + fill-opacity: 1; + fill-rule: nonzero; + stroke: #260314; + stroke-width: 1.5; + stroke-linecap: round; + stroke-linejoin: miter; + stroke-miterlimit: 4; + stroke-dasharray: none; + stroke-dashoffset: 10; + stroke-opacity: 1; } .chessB .chess-path-A { - opacity:1; - fill:#400827; - fill-opacity:1; - fill-rule:nonzero; - stroke:#260314; - stroke-width:1.5; - stroke-linecap:round; - stroke-linejoin:miter; - stroke-miterlimit:4; - stroke-dasharray:none; - stroke-dashoffset:10; - stroke-opacity:1; + opacity: 1; + fill: #400827; + fill-opacity: 1; + fill-rule: nonzero; + stroke: #260314; + stroke-width: 1.5; + stroke-linecap: round; + stroke-linejoin: miter; + stroke-miterlimit: 4; + stroke-dasharray: none; + stroke-dashoffset: 10; + stroke-opacity: 1; } .chessW .chess-path-B { - opacity:1; - fill:#ffe4aa; - fill-opacity:1; - fill-rule:evenodd; - stroke:#260314; - stroke-width:1.5; - stroke-linecap:round; - stroke-linejoin:round; - stroke-miterlimit:4; - stroke-dasharray:none; - stroke-opacity:1; + opacity: 1; + fill: #ffe4aa; + fill-opacity: 1; + fill-rule: evenodd; + stroke: #260314; + stroke-width: 1.5; + stroke-linecap: round; + stroke-linejoin: round; + stroke-miterlimit: 4; + stroke-dasharray: none; + stroke-opacity: 1; } .chessB .chess-path-B { - opacity:1; + opacity: 1; fill: #400827; - fill-opacity:1; - fill-rule:evenodd; - stroke:#260314; - stroke-width:1.5; - stroke-linecap:round; - stroke-linejoin:round; - stroke-miterlimit:4; - stroke-dasharray:none; - stroke-opacity:1; + fill-opacity: 1; + fill-rule: evenodd; + stroke: #260314; + stroke-width: 1.5; + stroke-linecap: round; + stroke-linejoin: round; + stroke-miterlimit: 4; + stroke-dasharray: none; + stroke-opacity: 1; } .chessW .chess-path-Bx { - opacity:1; - fill:#ffe4aa; - fill-opacity:1; - fill-rule:evenodd; - stroke:#260314; - stroke-width:1.5; - stroke-linecap:round; - stroke-linejoin:round; - stroke-miterlimit:4; - stroke-dasharray:none; - stroke-opacity:1; + opacity: 1; + fill: #ffe4aa; + fill-opacity: 1; + fill-rule: evenodd; + stroke: #260314; + stroke-width: 1.5; + stroke-linecap: round; + stroke-linejoin: round; + stroke-miterlimit: 4; + stroke-dasharray: none; + stroke-opacity: 1; } .chessB .chess-path-Bx { - opacity:1; + opacity: 1; fill: #ffe4aa; - fill-opacity:1; - fill-rule:evenodd; + fill-opacity: 1; + fill-rule: evenodd; stroke: #400827; - stroke-width:1.5; - stroke-linecap:round; - stroke-linejoin:round; - stroke-miterlimit:4; - stroke-dasharray:none; - stroke-opacity:1; + stroke-width: 1.5; + stroke-linecap: round; + stroke-linejoin: round; + stroke-miterlimit: 4; + stroke-dasharray: none; + stroke-opacity: 1; } .chessW .chess-path-C { - opacity:1; - fill:#400827; - fill-opacity:1; - stroke:#260314; - stroke-width:1.5; - stroke-linecap:round; - stroke-linejoin:round; - stroke-miterlimit:4; - stroke-dasharray:none; - stroke-opacity:1; + opacity: 1; + fill: #400827; + fill-opacity: 1; + stroke: #260314; + stroke-width: 1.5; + stroke-linecap: round; + stroke-linejoin: round; + stroke-miterlimit: 4; + stroke-dasharray: none; + stroke-opacity: 1; } .chessB .chess-path-C { opacity:1; - fill:#ffe4aa; - fill-opacity:1; - stroke:#ffe4aa; - stroke-width:1.5; - stroke-linecap:round; - stroke-linejoin:round; - stroke-miterlimit:4; - stroke-dasharray:none; - stroke-opacity:1; + fill: #ffe4aa; + fill-opacity: 1; + stroke: #ffe4aa; + stroke-width: 1.5; + stroke-linecap: round; + stroke-linejoin: round; + stroke-miterlimit: 4; + stroke-dasharray: none; + stroke-opacity: 1; } .chessW .chess-path-D { fill: #ffe4aa; fill-opacity: 0.75; - fill-rule:evenodd; + fill-rule: evenodd; stroke: #260314; - stroke-width:1; - stroke-linecap:round; - stroke-linejoin:mitter; - stroke-miterlimit:4; - stroke-dasharray:none; - stroke-opacity:1; + stroke-width: 1; + stroke-linecap: round; + stroke-linejoin: miter; + stroke-miterlimit: 4; + stroke-dasharray: none; + stroke-opacity: 1; } .chessB .chess-path-D { fill: #400827; fill-opacity: 0.75; - fill-rule:evenodd; + fill-rule: evenodd; stroke: #ffe4aa; - stroke-width:1; - stroke-linecap:round; - stroke-linejoin:mitter; - stroke-miterlimit:4; - stroke-dasharray:none; - stroke-opacity:1; + stroke-width: 1; + stroke-linecap: round; + stroke-linejoin: miter; + stroke-miterlimit: 4; + stroke-dasharray: none; + stroke-opacity: 1; } Modified: trunk/Toss/WebClient/index.html =================================================================== --- trunk/Toss/WebClient/index.html 2010-12-19 14:31:15 UTC (rev 1260) +++ trunk/Toss/WebClient/index.html 2010-12-19 17:35:10 UTC (rev 1261) @@ -126,8 +126,6 @@ </div> -<div id="opening" style="display: none;">Opening may take some time ...</div> - <div id="game-disp"> <p id="game-info-par"> <span id="game-title"></span> Deleted: trunk/Toss/WebClient/make_db.py =================================================================== --- trunk/Toss/WebClient/make_db.py 2010-12-19 14:31:15 UTC (rev 1260) +++ trunk/Toss/WebClient/make_db.py 2010-12-19 17:35:10 UTC (rev 1261) @@ -1,39 +0,0 @@ -#!/usr/bin/python - -import os -from pysqlite2 import dbapi2 as sqlite3 - -TUID = "toss_id_05174_" # from TossHandler import TUID - -print "Creating empty Toss DB" - -conn = sqlite3.connect("tossdb.sqlite") -conn.execute("create table users(id string primary key, name string, surname string, email string, passwd string)") -conn.execute("create table cur_states(playid int primary key, game string, player1 string, player2 string, move int, toss string, info string, svg string)") -conn.execute("create table old_states(playid int, game string, player1 string, player2 string, move int, toss string, info string, svg string)") -conn.execute("create table games(game string primary key, toss string)") -conn.execute("create table ports(port int primary key, locked bool)") -conn.execute("create table lock(tid int primary key, locked bool)") -conn.execute("create table friends(id string, fid string)") -conn.commit () - -conn.execute ("insert into lock(tid, locked) values (?, ?)", - (TUID, 'false')) - -def add_game (g): - f = open("../examples/" + g + ".toss") - toss = f.read() - f.close() - conn.execute ("insert into games(game, toss) values (?, ?)", (g, toss)) - -games = ["Breakthrough", "Chess", "Entanglement", "Gomoku", "Tic-Tac-Toe"] - -for g in games: - print ("Added " + g) - add_game (g) - -conn.commit () - -os.chmod ("tossdb.sqlite", 0777) - -print "Created tossdb.sqlite" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-19 14:31:22
|
Revision: 1260 http://toss.svn.sourceforge.net/toss/?rev=1260&view=rev Author: lukstafi Date: 2010-12-19 14:31:15 +0000 (Sun, 19 Dec 2010) Log Message: ----------- GDL parsing: initial commit, in progress. Modified Paths: -------------- trunk/Toss/Formula/Aux.ml trunk/Toss/Formula/Aux.mli trunk/Toss/Play/GDL.ml trunk/Toss/Play/GDL.mli trunk/Toss/Play/GameTest.ml trunk/Toss/Play/Server.ml Added Paths: ----------- trunk/Toss/Play/ServerGDLTest.in trunk/Toss/Play/ServerGDLTest.out Modified: trunk/Toss/Formula/Aux.ml =================================================================== --- trunk/Toss/Formula/Aux.ml 2010-12-19 12:26:22 UTC (rev 1259) +++ trunk/Toss/Formula/Aux.ml 2010-12-19 14:31:15 UTC (rev 1260) @@ -397,3 +397,17 @@ while true do Buffer.add_channel buf file 1 done with End_of_file -> ()); Buffer.contents buf + +let rec input_http_message file = + let buf = Buffer.create 256 in + let line = ref "POST / HTTP" in + let msg_len = ref 0 in + while !line <> "" && !line <> "\r" do + line := input_line file; + let line_len = String.length !line in + if line_len > 16 && String.sub !line 0 15 = "Content-length:" then + msg_len := int_of_string + (String.sub !line 16 (line_len - 16)); + done; + Buffer.add_channel buf file !msg_len; + Buffer.contents buf Modified: trunk/Toss/Formula/Aux.mli =================================================================== --- trunk/Toss/Formula/Aux.mli 2010-12-19 12:26:22 UTC (rev 1259) +++ trunk/Toss/Formula/Aux.mli 2010-12-19 14:31:15 UTC (rev 1260) @@ -185,3 +185,7 @@ (** Input a file to a string. *) val input_file : in_channel -> string + +(** Skip the header extracting the [Content-length] field and input the + content of an HTTP message. *) +val input_http_message : in_channel -> string Modified: trunk/Toss/Play/GDL.ml =================================================================== --- trunk/Toss/Play/GDL.ml 2010-12-19 12:26:22 UTC (rev 1259) +++ trunk/Toss/Play/GDL.ml 2010-12-19 14:31:15 UTC (rev 1260) @@ -41,3 +41,19 @@ (* game ends here: match id, actions on previous step *) let compile_game_descr entries = entries + +let client_player = ref (Const "uninitialized") +let game_description = ref [] + +let initialize_game player game_descr startcl = + client_player := player; + game_description := game_descr; + let effort, horizon, heur_adv_ratio = + 2, 100, 4.0 in + effort, horizon, heur_adv_ratio + +let translate_last_action actions = + "1", ["1","1"] + +let translate_move move new_state = + "NOOP" Modified: trunk/Toss/Play/GDL.mli =================================================================== --- trunk/Toss/Play/GDL.mli 2010-12-19 12:26:22 UTC (rev 1259) +++ trunk/Toss/Play/GDL.mli 2010-12-19 14:31:15 UTC (rev 1260) @@ -39,3 +39,13 @@ val compile_game_descr : game_descr_entry list -> game_description + +val initialize_game : + term -> game_description -> int -> int * int * float + +val translate_last_action : + term list -> string * (string * string) list + +(* FIXME: remove dependency on Game? *) +val translate_move : + Game.move -> Game.play_state -> string Modified: trunk/Toss/Play/GameTest.ml =================================================================== --- trunk/Toss/Play/GameTest.ml 2010-12-19 12:26:22 UTC (rev 1259) +++ trunk/Toss/Play/GameTest.ml 2010-12-19 14:31:15 UTC (rev 1260) @@ -561,6 +561,22 @@ Sys.remove "./Play/ServerTest.temp"; assert_equal ~printer:(fun x->x) target result ); + + "server: ServerGDLTest.in GDL Tic-Tac-Toe" >:: + (fun () -> + let in_ch = open_in "./Play/ServerGDLTest.in" in + let out_ch = open_out "./Play/ServerGDLTest.temp" in + (try while true do + Server.req_handle in_ch out_ch done + with End_of_file -> ()); + close_in in_ch; close_out out_ch; + let result = + Aux.input_file (open_in "./Play/ServerGDLTest.temp") in + let target = + Aux.input_file (open_in "./Play/ServerGDLTest.out") in + Sys.remove "./Play/ServerTest.temp"; + assert_equal ~printer:(fun x->x) target result + ); "play: breakthrough suggest in game" >:: (fun () -> Modified: trunk/Toss/Play/Server.ml =================================================================== --- trunk/Toss/Play/Server.ml 2010-12-19 12:26:22 UTC (rev 1259) +++ trunk/Toss/Play/Server.ml 2010-12-19 14:31:15 UTC (rev 1260) @@ -19,9 +19,9 @@ let play_state = ref (None : Game.play_state option) (* Timeout. *) -let dtimeout = ref (-1); +let dtimeout = ref (-1) +let playclock = ref 0 - (* -------------------- GENERAL SERVER AND REQUEST HANDLER ------------------ *) exception Host_not_found @@ -53,23 +53,21 @@ done let req_of_str s = - let http_beg = "POST / HTTP/" in - let http_beg_l = String.length http_beg in let s_len = String.length s in - if s_len > http_beg_l && String.sub s 0 http_beg_l = http_beg + if s_len > 4 && String.sub s 0 4 = "GDL " then - if Str.string_match (Str.regexp "\r?\n\r?\n") s 0 - then - let m_beg = Str.match_end () in - Aux.Right (GDLParser.parse_request KIFLexer.lex - (Lexing.from_string (String.sub s m_beg (s_len-m_beg)))) - else - raise (Lexer.Parsing_error "Empty HTTP message") + Aux.Right (GDLParser.parse_request KIFLexer.lex + (Lexing.from_string (String.sub s 4 (s_len-4)))) else Aux.Left (ArenaParser.parse_request Lexer.lex (Lexing.from_string s)) let rec read_in_line in_ch = - let line_in = input_line in_ch in + let line_in = + let rec nonempty () = + let line_in = input_line in_ch in + if line_in = "" || line_in = "\r" then nonempty () + else line_in in + nonempty () in let line_in_len = String.length line_in in (* TODO: who needs escaping? *) let line_in = @@ -77,12 +75,19 @@ (* String.escaped *) line_in else (* String.escaped *) (String.sub line_in 0 (line_in_len-1)) in - (* We put endlines, encoded by '$', back into the message. *) - let line = - String.concat "\n" - (Str.split (Str.regexp "\\$") line_in) in - if !debug_level > 0 then Printf.printf "Rcvd: %s\n%!" line; - line + let http_beg = "POST / HTTP/" in + let http_beg_l = String.length http_beg in + if line_in_len > http_beg_l && String.sub line_in 0 http_beg_l = http_beg + then + "GDL " ^ Aux.input_http_message in_ch + else + (* We put endlines, encoded by '$', back into the message. + TODO: perhaps a "better" solution now that HTTP has one? *) + let line = + String.concat "\n" + (Str.split (Str.regexp "\\$") line_in) in + if !debug_level > 0 then Printf.printf "Rcvd: %s\n%!" line; + line let possibly_modifies_game = function Arena.AddElem _ -> true @@ -142,8 +147,8 @@ let resp = match req with | Aux.Left (Arena.SuggestLocMoves - (loc, timer, effort, how, horizon, heuristic, - heur_adv_ratio)) -> ( + (loc, timer, effort, how, horizon, heuristic, + heur_adv_ratio)) -> ( Random.self_init (); (* TODO: should be in idle time, not now *) Gc.full_major (); @@ -173,13 +178,14 @@ Game.move_gs_str !state move | None -> "None" ) + | Aux.Left (Arena.ApplyRule (r_name, mtch, t, p) as req) -> ( if !game_modified then let (new_state, resp) = Arena.handle_request !state req in state := new_state; resp else - (* trying to restore [Server.play_state] so as to avoid - reinitialization *) + (* trying to restore [Server.play_state] so as to avoid + reinitialization *) let {Arena.rules=rules; graph=graph} = !state.Arena.game in let struc = !state.Arena.struc in let fn s n = Structure.find_elem s n in @@ -193,17 +199,17 @@ !state.Arena.struc graph.(!state.Arena.cur_loc) in try for i = 0 to Array.length moves - 1 do - (* FIXME: handle time and params! *) + (* FIXME: handle time and params! *) let mov = moves.(i) in if r_name = mov.Game.rule && - (* t = mov.Game.time && *) - (* something wrong with this: - List.for_all (fun (pn, pv) -> - pv = List.assoc pn mov.Game.parameters) p && *) + (* t = mov.Game.time && *) + (* something wrong with this: + List.for_all (fun (pn, pv) -> + pv = List.assoc pn mov.Game.parameters) p && *) List.for_all (fun (e, f) -> f = List.assoc e mov.Game.embedding) m - (* TODO: handle location matching *) + (* TODO: handle location matching *) then ( expected_location := mov.Game.next_loc; let _ = if !debug_level > 2 then @@ -211,8 +217,8 @@ !expected_location in raise (Found i)) done; - (* TODO: if not due to only time or params mismatch, - block or warn about invalid rule application *) + (* TODO: if not due to only time or params mismatch, + block or warn about invalid rule application *) let (new_state, resp) = Arena.handle_request !state req in if !debug_level > 0 then @@ -230,7 +236,7 @@ loc = !state.Arena.cur_loc} pos memory | _ -> failwith "req_handle: impossible" in state := new_state; - (* Rewriting doesn't handle location update. *) + (* Rewriting doesn't handle location update. *) let new_game_state = { Game.struc = new_state.Arena.struc; loc = moves.(pos).Game.next_loc; @@ -242,13 +248,179 @@ }; resp ) + | Aux.Left req -> game_modified := !game_modified || possibly_modifies_game req; let (new_state, resp) = Arena.handle_request !state req in state := new_state; resp - | Aux.Right req -> - failwith "GDL request parsed but handler not implemented yet" + + | Aux.Right (GDL.Start (_, player, game_descr, startcl, playcl)) -> + (* GDL will store the player and the game in its state. *) + let effort, horizon, heur_adv_ratio = + GDL.initialize_game player game_descr startcl in + (* TODO: handle timer (startclock) in Game.initialize_default*) + let p, ps = Game.initialize_default + !state ~effort ~search_method:"alpha_beta_ord" + ~horizon ~heur_adv_ratio () in + game_modified := false; + play := Some p; play_state := Some ps; + playclock := playcl; + "HTTP/1.0 200 OK\r\nContent-type: text/acl\r\nContent-length: 5" + ^ "\r\n\r\nREADY" + + + | Aux.Right (GDL.Play (_, actions)) -> + let time_started = int_of_float (Sys.time ()) in + let r_name, mtch = + GDL.translate_last_action actions in + + let {Arena.rules=rules; graph=graph} = !state.Arena.game in + let struc = !state.Arena.struc in + let fn s n = Structure.find_elem s n in + let r = List.assoc r_name rules in + let lhs = + r.ContinuousRule.discrete.DiscreteRule.lhs_struc in + let m = + List.map (fun (l, s) -> (fn lhs l, fn struc s)) mtch in + let moves = + Game.gen_moves Game.cGRID_SIZE rules + !state.Arena.struc graph.(!state.Arena.cur_loc) in + let pos = + (try + for i = 0 to Array.length moves - 1 do + (* FIXME: handle time and params! *) + let mov = moves.(i) in + if + r_name = mov.Game.rule && + (* t = mov.Game.time && *) + (* something wrong with this: + List.for_all (fun (pn, pv) -> + pv = List.assoc pn mov.Game.parameters) p && *) + List.for_all (fun (e, f) -> + f = List.assoc e mov.Game.embedding) m + (* TODO: handle location matching *) + then ( + expected_location := mov.Game.next_loc; + let _ = if !debug_level > 2 then + Printf.printf "expected_location = %d\n%!" + !expected_location in + raise (Found i)) + done; + (* TODO: if not due to only time or params mismatch, + block or warn about invalid rule application *) + failwith + "Server GDL Play request: action mismatched with play state" + with Found pos -> pos) in + let old_struc = !state.Arena.struc in + let req = Arena.ApplyRule (r_name, mtch, 0.1, []) in + let (new_state, resp) = Arena.handle_request !state req in + let memory = match !play, !play_state with + | Some play, Some {Game.memory=memory; game_state=pstate} -> + Game.update_memory + ~num_players:play.Game.game.Arena.num_players + {Game.struc=old_struc; + time = !state.Arena.time; + loc = !state.Arena.cur_loc} pos memory + | _ -> failwith "req_handle: impossible" in + state := new_state; + (* Rewriting doesn't handle location update. *) + let new_game_state = { + Game.struc = new_state.Arena.struc; + loc = moves.(pos).Game.next_loc; + time = new_state.Arena.time; + } in + play_state := Some { + Game.game_state = new_game_state; + memory = memory; + }; + + let time_used = + time_started - (int_of_float (ceil (Sys.time ()))) in + let p, ps = + match !play, !play_state with + | Some play, Some play_state -> + play, play_state + | _ -> assert false in + ignore (Unix.alarm (!playclock - time_used)); + let res = Game.suggest p ps in + Game.cancel_timeout (); + let mov_msg = + match res with + | Some (move, new_state) -> + play_state := Some new_state; + GDL.translate_move move new_state + | None -> "NOOP" in + let msg_len = String.length mov_msg in + "HTTP/1.0 200 OK\r\nContent-type: text/acl\r\nContent-length: " + ^ string_of_int msg_len ^ "\r\n\r\n" ^ mov_msg + + | Aux.Right (GDL.Stop (_, actions)) -> + let r_name, mtch = + GDL.translate_last_action actions in + + let {Arena.rules=rules; graph=graph} = !state.Arena.game in + let struc = !state.Arena.struc in + let fn s n = Structure.find_elem s n in + let r = List.assoc r_name rules in + let lhs = + r.ContinuousRule.discrete.DiscreteRule.lhs_struc in + let m = + List.map (fun (l, s) -> (fn lhs l, fn struc s)) mtch in + let moves = + Game.gen_moves Game.cGRID_SIZE rules + !state.Arena.struc graph.(!state.Arena.cur_loc) in + let pos = + (try + for i = 0 to Array.length moves - 1 do + (* FIXME: handle time and params! *) + let mov = moves.(i) in + if + r_name = mov.Game.rule && + (* t = mov.Game.time && *) + (* something wrong with this: + List.for_all (fun (pn, pv) -> + pv = List.assoc pn mov.Game.parameters) p && *) + List.for_all (fun (e, f) -> + f = List.assoc e mov.Game.embedding) m + (* TODO: handle location matching *) + then ( + expected_location := mov.Game.next_loc; + let _ = if !debug_level > 2 then + Printf.printf "expected_location = %d\n%!" + !expected_location in + raise (Found i)) + done; + (* TODO: if not due to only time or params mismatch, + block or warn about invalid rule application *) + failwith + "Server GDL Play request: action mismatched with play state" + with Found pos -> pos) in + let old_struc = !state.Arena.struc in + let req = Arena.ApplyRule (r_name, mtch, 0.1, []) in + let (new_state, resp) = Arena.handle_request !state req in + let memory = match !play, !play_state with + | Some play, Some {Game.memory=memory; game_state=pstate} -> + Game.update_memory + ~num_players:play.Game.game.Arena.num_players + {Game.struc=old_struc; + time = !state.Arena.time; + loc = !state.Arena.cur_loc} pos memory + | _ -> failwith "req_handle: impossible" in + state := new_state; + (* Rewriting doesn't handle location update. *) + let new_game_state = { + Game.struc = new_state.Arena.struc; + loc = moves.(pos).Game.next_loc; + time = new_state.Arena.time; + } in + play_state := Some { + Game.game_state = new_game_state; + memory = memory; + }; + "HTTP/1.0 200 OK\r\nContent-type: text/acl\r\nContent-length: 4" + ^ "\r\n\r\nDONE" + in if !debug_level > 0 then print_endline ("Repl: " ^ resp ^ "\n"); output_string out_ch (resp ^ "\n"); Added: trunk/Toss/Play/ServerGDLTest.in =================================================================== --- trunk/Toss/Play/ServerGDLTest.in (rev 0) +++ trunk/Toss/Play/ServerGDLTest.in 2010-12-19 14:31:15 UTC (rev 1260) @@ -0,0 +1,62 @@ +POST / HTTP/1.0 +Accept: text/delim +Sender: GAMEMASTER +Receiver: GAMEPLAYER +Content-type: text/acl +Content-length: 1587 + +(START MATCH.3316980891 X (ROLE X) (ROLE O) (INIT (CELL 1 1 B)) (INIT (CELL 1 2 B)) (INIT (CELL 1 3 B)) (INIT (CELL 2 1 B)) (INIT (CELL 2 2 B)) (INIT (CELL 2 3 B)) (INIT (CELL 3 1 B)) (INIT (CELL 3 2 B)) (INIT (CELL 3 3 B)) (INIT (CONTROL X)) (<= (NEXT (CELL ?X ?Y ?PLAYER)) (DOES ?PLAYER (MARK ?X ?Y))) (<= (NEXT (CELL ?X ?Y ?MARK)) (TRUE (CELL ?X ?Y ?MARK)) (DOES ?PLAYER (MARK ?M ?N)) (DISTINCTCELL ?X ?Y ?M ?N)) (<= (NEXT (CONTROL X)) (TRUE (CONTROL O))) (<= (NEXT (CONTROL O)) (TRUE (CONTROL X))) (<= (ROW ?X ?PLAYER) (TRUE (CELL ?X 1 ?PLAYER)) (TRUE (CELL ?X 2 ?PLAYER)) (TRUE (CELL ?X 3 ?PLAYER))) (<= (COLUMN ?Y ?PLAYER) (TRUE (CELL 1 ?Y ?PLAYER)) (TRUE (CELL 2 ?Y ?PLAYER)) (TRUE (CELL 3 ?Y ?PLAYER))) (<= (DIAGONAL ?PLAYER) (TRUE (CELL 1 1 ?PLAYER)) (TRUE (CELL 2 2 ?PLAYER)) (TRUE (CELL 3 3 ?PLAYER))) (<= (DIAGONAL ?PLAYER) (TRUE (CELL 1 3 ?PLAYER)) (TRUE (CELL 2 2 ?PLAYER)) (TRUE (CELL 3 1 ?PLAYER))) (<= (LINE ?PLAYER) (ROW ?X ?PLAYER)) (<= (LINE ?PLAYER) (COLUMN ?Y ?PLAYER)) (<= (LINE ?PLAYER) (DIAGONAL ?PLAYER)) (<= OPEN (TRUE (CELL ?X ?Y B))) (<= (DISTINCTCELL ?X ?Y ?M ?N) (DISTINCT ?X ?M)) (<= (DISTINCTCELL ?X ?Y ?M ?N) (DISTINCT ?Y ?N)) (<= (LEGAL ?PLAYER (MARK ?X ?Y)) (TRUE (CELL ?X ?Y B)) (TRUE (CONTROL ?PLAYER))) (<= (LEGAL ?PLAYER NOOP) (NOT (TRUE (CONTROL ?PLAYER)))) (<= (GOAL ?PLAYER 100) (LINE ?PLAYER)) (<= (GOAL ?PLAYER 50) (NOT (LINE X)) (NOT (LINE O)) (NOT OPEN)) (<= (GOAL ?PLAYER1 0) (LINE ?PLAYER2) (DISTINCT ?PLAYER1 ?PLAYER2)) (<= (GOAL ?PLAYER 0) (NOT (LINE X)) (NOT (LINE O)) OPEN) (<= TERMINAL (LINE ?PLAYER)) (<= TERMINAL (NOT OPEN)) 30 30) + +POST / HTTP/1.0 +Accept: text/delim +Sender: GAMEMASTER +Receiver: GAMEPLAYER +Content-type: text/acl +Content-length: 27 + +(PLAY MATCH.3316980891 NIL) + +POST / HTTP/1.0 +Accept: text/delim +Sender: GAMEMASTER +Receiver: GAMEPLAYER +Content-type: text/acl +Content-length: 41 + +(PLAY MATCH.3316980891 ((MARK 3 3) NOOP)) + +POST / HTTP/1.0 +Accept: text/delim +Sender: GAMEMASTER +Receiver: GAMEPLAYER +Content-type: text/acl +Content-length: 41 + +(PLAY MATCH.3316980891 (NOOP (MARK 1 3))) + +POST / HTTP/1.0 +Accept: text/delim +Sender: GAMEMASTER +Receiver: GAMEPLAYER +Content-type: text/acl +Content-length: 41 + +(PLAY MATCH.3316980891 ((MARK 2 2) NOOP)) + +POST / HTTP/1.0 +Accept: text/delim +Sender: GAMEMASTER +Receiver: GAMEPLAYER +Content-type: text/acl +Content-length: 41 + +(PLAY MATCH.3316980891 (NOOP (MARK 1 2))) + +POST / HTTP/1.0 +Accept: text/delim +Sender: GAMEMASTER +Receiver: GAMEPLAYER +Content-type: text/acl +Content-length: 41 + +(STOP MATCH.3316980891 ((MARK 1 1) NOOP)) Added: trunk/Toss/Play/ServerGDLTest.out =================================================================== --- trunk/Toss/Play/ServerGDLTest.out (rev 0) +++ trunk/Toss/Play/ServerGDLTest.out 2010-12-19 14:31:15 UTC (rev 1260) @@ -0,0 +1,36 @@ +HTTP/1.0 200 OK +Content-type: text/acl +Content-length: 5 + +READY +HTTP/1.0 200 OK +Content-type: text/acl +Content-length: 10 + +(MARK 3 3) +HTTP/1.0 200 OK +Content-type: text/acl +Content-length: 4 + +NOOP +HTTP/1.0 200 OK +Content-type: text/acl +Content-length: 10 + +(MARK 2 2) +HTTP/1.0 200 OK +Content-type: text/acl +Content-length: 4 + +NOOP +HTTP/1.0 200 OK +Content-type: text/acl +Content-length: 10 + +(MARK 1 1) +HTTP/1.0 200 OK +Content-type: text/acl +Content-length: 4 + +DONE +ERR processing completed -- EOF This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-19 12:26:28
|
Revision: 1259 http://toss.svn.sourceforge.net/toss/?rev=1259&view=rev Author: lukaszkaiser Date: 2010-12-19 12:26:22 +0000 (Sun, 19 Dec 2010) Log Message: ----------- Bugfix for a concurrency problem in db, other small corrections. Modified Paths: -------------- trunk/Toss/WebClient/Connect.js trunk/Toss/WebClient/Handler.py trunk/Toss/WebClient/Main.js trunk/Toss/WebClient/README trunk/Toss/WebClient/Style.css trunk/Toss/WebClient/index.html Modified: trunk/Toss/WebClient/Connect.js =================================================================== --- trunk/Toss/WebClient/Connect.js 2010-12-19 01:18:01 UTC (rev 1258) +++ trunk/Toss/WebClient/Connect.js 2010-12-19 12:26:22 UTC (rev 1259) @@ -12,8 +12,8 @@ var SVG_HEIGHT = 500; var SVG_MARGINX = 50; var SVG_MARGINY = 50; -var VIEW_WIDTH = "19em"; -var VIEW_HEIGHT = "19em"; +var VIEW_WIDTH = "20em"; +var VIEW_HEIGHT = "20em"; var VIEW_MIRROR = 0; var GAME_NAME = ""; // name of current game, e.g. "Breakthrough" Modified: trunk/Toss/WebClient/Handler.py =================================================================== --- trunk/Toss/WebClient/Handler.py 2010-12-19 01:18:01 UTC (rev 1258) +++ trunk/Toss/WebClient/Handler.py 2010-12-19 12:26:22 UTC (rev 1259) @@ -97,14 +97,23 @@ moves_s = str(client.cur_moves()) return (dim_s + "$" + model_s + "$" + rels_s + "$" + moves_s) -def new_play (db, client, game, p1, p2, pid, move): +def get_free_id (db): + fid = 0 + for f in db.execute ("select count(*) from cur_states"): + fid = int(f[0]) + return (fid + 1) + +def new_play (db, client, game, p1, p2, move): res = get_all_from_db (db, "games", "game='" + game + "'") (_, toss) = res[0] client.open_from_str (toss) info = get_game_info (client) model = client.get_model () + get_global_lock (db) + pid = get_free_id (db) db_cur_insert (db, game, p1, p2, pid, move, model, info, "") - return (info) + release_global_lock (db) + return (str(pid) + "$" + info) def game_select_s (g, p1, p2, pid, m): return("game='" + g + "' and player1='" + p1 + "' and player2='" + p2 + @@ -116,21 +125,25 @@ (_, _, _, _, _, _, info, _) = res[0] return (info) +def db_escape (s): + return (s.replace("'", "''")) def move_play (db, client, move_tup, g, p1, p2, pid, m): - select_s = game_select_s (g, p1, p2, pid, m) - old_res = get_all_from_db (db, "cur_states", select_s) + sel_s = game_select_s (g, p1, p2, pid, m) + old_res = get_all_from_db (db, "cur_states", sel_s) (_, _, _, _, _, old_toss, old_info, old_svg) = old_res[0] res = get_all_from_db (db, "games", "game='" + g + "'") (_, game_toss) = res[0] client.open_from_str (game_toss + "\n MODEL " + old_toss) (move1, move2, move3) = move_tup client.make_move (move1, move2, move3) - new_toss = client.get_model () + new_toss = db_escape (client.get_model ()) new_info = get_game_info (client) - db.execute ("delete from cur_states where " + select_s) + new_info_db = db_escape (new_info) + db.execute ("update cur_states set toss='" + new_toss + "' where " + sel_s) + db.execute ("update cur_states set info='"+ new_info_db +"' where "+ sel_s) + db.execute ("update cur_states set move=" + str(int(m)+1) +" where "+ sel_s) db_old_insert (db, g, p1, p2, pid, m, old_toss, old_info, old_svg) - db_cur_insert (db, g, p1, p2, pid, int(m) + 1, new_toss, new_info, "") return (new_info) def upd_svg (db, g, p1, p2, pid, m, svg_s): @@ -218,12 +231,6 @@ db.commit () return ("OK") -def get_free_id (db): - fid = 0 - for f in db.execute ("select count(*) from cur_states"): - fid = int(f[0]) - return (fid + 1) - def handler(req): req.content_type = "text/plain" db = sqlite3.connect(DB_FILE) @@ -259,9 +266,6 @@ Cookie.add_cookie(req, cookie2) req.write ("User logged out: " + usr + ".") return apache.OK - if cmd == "FREEID": - req.write(str(get_free_id (db))) - return apache.OK if cmd == "ADDOPP": req.write(str(add_opponent (db, usr, data))) return apache.OK Modified: trunk/Toss/WebClient/Main.js =================================================================== --- trunk/Toss/WebClient/Main.js 2010-12-19 01:18:01 UTC (rev 1258) +++ trunk/Toss/WebClient/Main.js 2010-12-19 12:26:22 UTC (rev 1259) @@ -92,7 +92,7 @@ document.getElementById('cur-move').innerHTML = "none"; } else { document.getElementById('cur-move').innerHTML = - m_rule + ': <br/>' + m_str; + m_rule + ': ' + m_str; } CUR_ELEMS = m_act; CUR_MOVE = m.toString(); @@ -306,7 +306,10 @@ if (opp_uid == -1) { opp_uid = UNAME; } if (opp_uid == 0 || UNAME == "") { return; } document.getElementById("plays-list-" + GAME_NAME).style.display = "block"; - FREE_PLAY_NO = parseInt(srv("FREEID", "play")) + info_nbr = srv ("NEW_PLAY", "c, '" + GAME_NAME + "', '" + UNAME + + "', '" + opp_uid + "', 0"); + info_idx = info_nbr.indexOf('$'); + FREE_PLAY_NO = parseInt(info_nbr.substring(0, info_idx)); document.getElementById("play-number").innerHTML = "" + FREE_PLAY_NO; CUR_PLAY_I = PLAYS.length; VIEW_MIRROR = 0; @@ -315,9 +318,7 @@ document.getElementById("plays").style.left = "30em"; var p = [UNAME, opp_uid, FREE_PLAY_NO, 0]; PLAYS.push(p); - var fn = play_py_id (CUR_PLAY_I); - info = srv ("NEW_PLAY", "c, " + fn); - set_info(info); + set_info(info_nbr.substring(info_idx+1)); full_redraw (); srv ("UPD_SVG", play_py_id(CUR_PLAY_I) + ", " + svg_string()); li = new_play_item (GAME_NAME, CUR_PLAY_I); Modified: trunk/Toss/WebClient/README =================================================================== --- trunk/Toss/WebClient/README 2010-12-19 01:18:01 UTC (rev 1258) +++ trunk/Toss/WebClient/README 2010-12-19 12:26:22 UTC (rev 1259) @@ -21,7 +21,6 @@ TODO: - move interface: first click all, second click toggle, if one - confirm msg - move suggestions and play against computer - - after the above: remove left-of-board div, confirm in the middle - after the above: show game result in the middle / instead of move - sort plays by who's turn it is - option to give up game and offer a draw Modified: trunk/Toss/WebClient/Style.css =================================================================== --- trunk/Toss/WebClient/Style.css 2010-12-19 01:18:01 UTC (rev 1258) +++ trunk/Toss/WebClient/Style.css 2010-12-19 12:26:22 UTC (rev 1259) @@ -14,6 +14,7 @@ .bt { border-color: #260314; border-radius: 4px; + -moz-border-radius: 4px; border-width: 1px; color: #260314; background-color: #ffe4aa; @@ -35,6 +36,7 @@ .dbt { border-color: #ffe4aa; border-radius: 4px; + -moz-border-radius: 4px; border-width: 0px; color: #ffe4aa; background-color: #400827; @@ -71,6 +73,7 @@ .loginput { border-color: #ffe4aa; border-radius: 4px; + -moz-border-radius: 4px; border-width: 1px; position: relative; top: 2px; @@ -79,6 +82,7 @@ .forminput { border-color: #ffe4aa; border-radius: 4px; + -moz-border-radius: 4px; border-width: 2px; position: relative; top: 2px; @@ -108,6 +112,7 @@ background-color: #ffffff; border-color: #ffe4aa; border-radius: 4px; + -moz-border-radius: 4px; border-width: 1px; } @@ -125,6 +130,7 @@ background-color: #400827; border-color: #ffe4aa; border-radius: 4px; + -moz-border-radius: 4px; border-width: 0px; } @@ -320,6 +326,7 @@ width: 6em; border-color: #260314; border-radius: 4px; + -moz-border-radius: 4px; border-width: 1px; color: #260314; background-color: #ffe4aa; @@ -352,24 +359,24 @@ padding-left: 1.25em; } -.short { - max-width: 40em; +#game-disp { + position: relative; + top: -1em; + left: 0em; + width: 30em; + display: none; } -#features-list { - list-style: square; -} - -#game-title { - font-size: 1.2em; +#game-info-par { font-weight: bold; - margin-top: 1em; - margin-bottom: 2em; + margin-bottom: 0px; + margin-top: 0.5em; + padding: 0px; } -#game-disp { - position: relative; - display: none; +#move-info-par { + margin-top: 0.5em; + padding: 0px; } #game-desc { @@ -384,12 +391,10 @@ #board { position: absolute; - left: 9em; - padding-right: 1em; - top: 0px; + left: 0em; + top: 3.5em; width: 20em; - height: 19em; - border-right: 1px solid #260314; + height: 20em; } #working { @@ -418,27 +423,11 @@ padding: 1em; } -#move { - position: absolute; - left: 0px; - top: 0px; -} - -#play-no-div { - padding-bottom: 0.5em; - padding-left: 1em; -} - #cur-move, #cur-player { - padding-left: 1em; - margin-top: 0.5em; - margin-bottom: 0.5em; + margin-top: 0em; + margin-bottom: 0em; } -#mk-move { - padding-left: 0em; -} - .game-par { padding-top: 2px; border-top: 2px solid #260314; Modified: trunk/Toss/WebClient/index.html =================================================================== --- trunk/Toss/WebClient/index.html 2010-12-19 01:18:01 UTC (rev 1258) +++ trunk/Toss/WebClient/index.html 2010-12-19 12:26:22 UTC (rev 1259) @@ -68,7 +68,7 @@ <div id="welcome"> <p id="welcome-top">Enjoy games on <span class="logo-in">tPlay</span></p> -<p class="short"> +<p> Strategic games are fun! <a href="register.html">Register</a>, login and enjoy <span class="logo-in">tPlay</span>!</p> @@ -93,8 +93,6 @@ </ul> </div> -<div id="game-title"></div> - <div id="plays"> <p class="game-par"> <button class="bt" onclick="new_play ('Breakthrough')">New Game</button> @@ -131,16 +129,17 @@ <div id="opening" style="display: none;">Opening may take some time ...</div> <div id="game-disp"> - <div id="move"> - <div id="play-no-div">Game <span id="play-number">?</span></div> - Active player:<br/> - <div id="cur-player"></div> - Chosen move:<br/> - <div id="cur-move">none</div> - <div id="mk-move"> - <button class="bt" onclick="make_move ()">Make move</button> - </div> - </div> + <p id="game-info-par"> + <span id="game-title"></span> + game <span id="play-number">?</span>, + <span id="cur-player"></span> moving + </p> + + <p id="move-info-par"> + <button id="movebt" class="bt" onclick="make_move ()">Make move:</button> + <span id="cur-move">none</span> + </p> + <div id="board"><div id="working">Working...</div></div> </div> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-19 01:18:28
|
Revision: 1258 http://toss.svn.sourceforge.net/toss/?rev=1258&view=rev Author: lukstafi Date: 2010-12-19 01:18:01 +0000 (Sun, 19 Dec 2010) Log Message: ----------- GDL parser: initial commit, missing config. Modified Paths: -------------- trunk/Toss/menhir_conf Modified: trunk/Toss/menhir_conf =================================================================== --- trunk/Toss/menhir_conf 2010-12-19 00:46:44 UTC (rev 1257) +++ trunk/Toss/menhir_conf 2010-12-19 01:18:01 UTC (rev 1258) @@ -30,9 +30,14 @@ incl="$Ptoks" fi -menhir_s="menhir --base ${last_arg%%.*} --external-tokens Lexer $incl $args" +if [[ $last_arg = *GDLParser.mly ]]; then + menhir_s="menhir --base ${last_arg%%.*} --external-tokens KIFLexer $args" +else + menhir_s="menhir --base ${last_arg%%.*} --external-tokens Lexer $incl $args" +fi + echo "menhir $last_arg" -#echo $menhir_s +echo $menhir_s # Below we use sed to hide warnings about unused tokens from Tokens.mly # These are not meaningfull as we use one tokens file for everything. eval "$menhir_s 2>&1 | sed '/Warning: the token/d' | sed '/Tokens.mly/d' 1>&2" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-19 00:46:51
|
Revision: 1257 http://toss.svn.sourceforge.net/toss/?rev=1257&view=rev Author: lukstafi Date: 2010-12-19 00:46:44 +0000 (Sun, 19 Dec 2010) Log Message: ----------- GDL parser: initial commit, missing files. Added Paths: ----------- trunk/Toss/Play/GDL.ml trunk/Toss/Play/GDL.mli trunk/Toss/Play/GDLParser.mly trunk/Toss/Play/KIFLexer.mll Added: trunk/Toss/Play/GDL.ml =================================================================== --- trunk/Toss/Play/GDL.ml (rev 0) +++ trunk/Toss/Play/GDL.ml 2010-12-19 00:46:44 UTC (rev 1257) @@ -0,0 +1,43 @@ +(** {2 Game Description Language.} + + Type definitions, helper functions, game specification translation. *) + +type term = + | Const of string + | Var of string + | Func of string * term list + +type atom = + | Distinct of term list + | Rel of string * term list + | Currently of term + | Does of term * term + +type literal = + | Pos of atom + | Neg of atom + +type game_descr_entry = + | Datalog of string * term list * literal list + | Next of term * literal list + | Legal of term * term * literal list + | Goal of term * int * literal list + | Terminal of literal list + | Role of term + | Initial of term * literal list + | Atomic of string * term list + + +(* Pbbly will change to a compiled form. *) +type game_description = + game_descr_entry list + +type request = + | Start of string * term * game_description * int * int + (* prepare game: match id, role, game, startclock, playclock *) + | Play of string * term list + (* request a move: match id, actions on previous step *) + | Stop of string * term list + (* game ends here: match id, actions on previous step *) + +let compile_game_descr entries = entries Added: trunk/Toss/Play/GDL.mli =================================================================== --- trunk/Toss/Play/GDL.mli (rev 0) +++ trunk/Toss/Play/GDL.mli 2010-12-19 00:46:44 UTC (rev 1257) @@ -0,0 +1,41 @@ +(** {2 Game Description Language.} + + Type definitions, helper functions, game specification translation. *) + +type term = + | Const of string + | Var of string + | Func of string * term list + +type atom = + | Distinct of term list + | Rel of string * term list + | Currently of term + | Does of term * term + +type literal = + | Pos of atom + | Neg of atom + +type game_descr_entry = + | Datalog of string * term list * literal list + | Next of term * literal list + | Legal of term * term * literal list + | Goal of term * int * literal list + | Terminal of literal list + | Role of term + | Initial of term * literal list + | Atomic of string * term list + +type game_description + +type request = + | Start of string * term * game_description * int * int + (* prepare game: match id, role, game, startclock, playclock *) + | Play of string * term list + (* request a move: match id, actions on previous step *) + | Stop of string * term list + (* game ends here: match id, actions on previous step *) + +val compile_game_descr : + game_descr_entry list -> game_description Added: trunk/Toss/Play/GDLParser.mly =================================================================== --- trunk/Toss/Play/GDLParser.mly (rev 0) +++ trunk/Toss/Play/GDLParser.mly 2010-12-19 00:46:44 UTC (rev 1257) @@ -0,0 +1,140 @@ +%{ + open KIFLexer + + open GDL +%} + +%token <string> WORD +%token <string> INDVAR +%token <string> SEQVAR +%token OPEN CLOSE COMMA QUOTE SEMICOLON BACKQUOTE DBLQUOTE SHARP DOT +%token NOT_EQ NOT AND OR IMPL REVIMPL EQUIV LISTOF SETOF QUOTE_KWD +%token IF COND THE SETOFALL KAPPA LAMBDA RULE_RIGHT RULE_LEFT CONSIS +%token DEFOBJECT DEFUNCTION DEFRELATION ASSIGN ASSIGN_IMPLIES ASSIGN_AND +%token FORALL EXISTS EOF + + +%start parse_game_description parse_request +%type <GDL.request> parse_request request +%type <GDL.game_description> parse_game_description game_description + + +%% + + +term: +| v=INDVAR { Var v } +| c=WORD { Const c } +| sexp=delimited (OPEN, list (term), CLOSE) + { match sexp with + | Const c::args -> Func (c, args) + | _ -> raise (Lexer.Parsing_error "GDL term: not a constant head") + } + +atom: +| r=WORD { Rel (r, []) } +| sexp=delimited (OPEN, list (term), CLOSE) + { match sexp with + | Const "distinct"::args -> Distinct args + | [Const "true"; arg] -> Currently arg + | [Const "does"; player; action] -> Does (player, action) + | Const r::args -> Rel (r, args) + | _ -> raise (Lexer.Parsing_error "GDL atom: not a constant head") + } + +literal: +| a=atom { Pos a } +| OPEN NOT a=atom CLOSE { Neg a } + +game_descr_entry: +| OPEN REVIMPL head=atom body=list (literal) CLOSE + { match head with + | Rel ("next", [t]) -> Next (t, body) + | Rel ("next", _) -> + raise (Lexer.Parsing_error "GDL next: not unary") + | Rel ("init", [arg]) -> Initial (arg, body) + | Rel ("init", _) -> + raise (Lexer.Parsing_error "GDL init: not unary") + | Rel ("terminal", []) -> Terminal body + | Rel ("terminal", _) -> + raise (Lexer.Parsing_error "GDL terminal: not nullary") + | Rel ("legal", [t1; t2]) -> Legal (t1, t2, body) + | Rel ("legal", _) -> + raise (Lexer.Parsing_error "GDL legal: not binary") + | Rel ("goal", [t; Const gv]) -> + (try + let gv = int_of_string gv in + Goal (t, gv, body) + with Failure _ | Invalid_argument _ -> + raise (Lexer.Parsing_error "GDL goal: value not a constant int")) + | Rel ("goal", _) -> + raise (Lexer.Parsing_error + "GDL goal: not binary or value not constant") + | Rel (r, args) -> Datalog (r, args, body) + | Currently _ -> + raise (Lexer.Parsing_error "GDL rule: \"true\" in head") + | Distinct _ -> + raise (Lexer.Parsing_error "GDL rule: \"distinct\" in head") + | Does _ -> + raise (Lexer.Parsing_error "GDL rule: \"does\" in head") + } +| a=atom + { match a with + | Rel ("init", [arg]) -> Initial (arg, []) + | Rel ("init", _) -> + raise (Lexer.Parsing_error "GDL init: not unary") + | Rel ("role", [arg]) -> Role arg + | Rel ("role", _) -> + raise (Lexer.Parsing_error "GDL role: not unary") + | Rel (r, args) -> Atomic (r, args) + | _ -> + raise (Lexer.Parsing_error + "GDL atomic entry: not init, role nor fact") + } + +%public game_description: + OPEN descr=list(game_descr_entry) CLOSE + { compile_game_descr descr } + +%public request: +| OPEN start=WORD id=WORD role=term descr=game_description + startclock=WORD playclock=WORD + { + if start <> "START" && start <> "start" then + raise (Lexer.Parsing_error "GDL request: start request expected") + else + try + let startclock = int_of_string startclock in + let playclock = int_of_string playclock in + Start (id, role, descr, startclock, playclock) + with Failure _ | Invalid_argument _ -> + raise (Lexer.Parsing_error "GDL start: clock not a constant int") + } +| OPEN command=WORD id=WORD actions=delimited (OPEN, list(term), CLOSE) + { + if command = "PLAY" || command = "play" then + Play (id, actions) + else if command = "STOP" || command = "stop" then + Stop (id, actions) + else raise + (Lexer.Parsing_error + "GDL request: play or stop request expected") + } +| OPEN command=WORD id=WORD actions=WORD + { + if actions = "nil" || actions = "NIL" then ( + if command = "PLAY" || command = "play" then + Play (id, []) + else if command = "STOP" || command = "stop" then + Stop (id, []) + else raise + (Lexer.Parsing_error "GDL request: play or stop request expected") + ) else raise + (Lexer.Parsing_error "GDL request: action list expected") + } + +parse_game_description: + | game_description EOF { $1 } + +parse_request: + | request EOF { $1 } Added: trunk/Toss/Play/KIFLexer.mll =================================================================== --- trunk/Toss/Play/KIFLexer.mll (rev 0) +++ trunk/Toss/Play/KIFLexer.mll 2010-12-19 00:46:44 UTC (rev 1257) @@ -0,0 +1,151 @@ +{ +type token = + | WORD of string + | INDVAR of string + | SEQVAR of string + | OPEN + | CLOSE + | COMMA + | QUOTE + | SEMICOLON + | BACKQUOTE + | DBLQUOTE + | SHARP + | DOT + | NOT_EQ + | NOT + | AND + | OR + | IMPL + | REVIMPL + | EQUIV + | LISTOF + | SETOF + | QUOTE_KWD + | IF + | COND + | THE + | SETOFALL + | KAPPA + | LAMBDA + | RULE_RIGHT + | RULE_LEFT + | CONSIS + | DEFOBJECT + | DEFUNCTION + | DEFRELATION + | ASSIGN + | ASSIGN_IMPLIES + | ASSIGN_AND + | FORALL + | EXISTS + | EOF + +let reset_as_file lexbuf s = + let pos = lexbuf.Lexing.lex_curr_p in + lexbuf.Lexing.lex_curr_p <- { pos with + Lexing.pos_lnum = 1; + pos_fname = s; + pos_bol = pos.Lexing.pos_cnum; + } + + +let incr_lineno lexbuf = + let pos = lexbuf.Lexing.lex_curr_p in + lexbuf.Lexing.lex_curr_p <- { pos with + Lexing.pos_lnum = pos.Lexing.pos_lnum + 1; + pos_bol = pos.Lexing.pos_cnum; + } + +let move_lines_by lexbuf s = + let nbrk = ref 0 in + for i = 0 to String.length s - 1 do + if s.[i] = '\n' then incr nbrk + done; + if !nbrk > 0 then + let pos = lexbuf.Lexing.lex_curr_p in + lexbuf.Lexing.lex_curr_p <- { pos with + Lexing.pos_lnum = pos.Lexing.pos_lnum + !nbrk; + pos_bol = pos.Lexing.pos_cnum; + } + + +(* Parsing errors are about both syntax and semantics. *) +exception Parsing_error of string + +let print_error_trace = ref true + +let report_parsing_error startpos endpos s = + let clbeg = + startpos.Lexing.pos_cnum - startpos.Lexing.pos_bol in + ignore (Format.flush_str_formatter ()); + let err_msg = + Printf.sprintf + "File \"%s\", lines %d-%d, characters %d-%d:\n%s" + startpos.Lexing.pos_fname startpos.Lexing.pos_lnum + endpos.Lexing.pos_lnum clbeg + (clbeg+(endpos.Lexing.pos_cnum - startpos.Lexing.pos_cnum)) + s in + if !print_error_trace then + print_endline err_msg; + raise (Parsing_error err_msg) + +} + +rule lex = parse + | [' ' '\t' '\r'] { lex lexbuf } + | "\r\n" { incr_lineno lexbuf; lex lexbuf } + | '\n' { incr_lineno lexbuf; lex lexbuf } + | '(' { OPEN } + | ')' { CLOSE } + | ',' { COMMA } + | '\'' { QUOTE } + | ';' { SEMICOLON } + | '`' { BACKQUOTE } + | '"' { DBLQUOTE } + | '#' { SHARP } + | '.' { DOT } + | "/=" { NOT_EQ } + | "not" { NOT } + | "and" { AND } + | "or" { OR } + | "=>" { IMPL } + | "<=" { REVIMPL } + | "<=>" { EQUIV } + | "listof" { LISTOF } + | "setof" { SETOF } + | "quote" { QUOTE_KWD } + | "if" { IF } + | "cond" { COND } + | "the" { THE } + | "setofall" { SETOFALL } + | "kappa" { KAPPA } + | "lambda" { LAMBDA } + | "=>>" { RULE_RIGHT } + | "<<=" { RULE_LEFT } + | "consis" { CONSIS } + | "defobject" { DEFOBJECT } + | "defunction" { DEFUNCTION } + | "defrelation" { DEFRELATION } + | ":=" { ASSIGN } + | ":=>" { ASSIGN_IMPLIES } + | ":&" { ASSIGN_AND } + | "forall" { FORALL } + | "exists" { EXISTS } + | ['!' '$' '%' '&' '*' '+' '-' '/' '0'-'9' ':' '<' '>' + 'A'-'Z' '[' ']' '^' '_' 'a'-'z' '{' '|' '}' '~'] as s + {WORD (Char.escaped s)} + | ['!' '$' '%' '&' '*' '+' '-' '.' '/' '0'-'9' ':' '<' '>' + 'A'-'Z' '[' ']' '^' '_' 'a'-'z' '{' '|' '}' '~'] + ['!' '$' '%' '&' '*' '+' '-' '.' '/' '0'-'9' ':' '<' '>' '?' '@' + 'A'-'Z' '[' ']' '^' '_' 'a'-'z' '{' '|' '}' '~']+ as s + {WORD s} + | '?' + ['!' '$' '%' '&' '*' '+' '-' '.' '/' '0'-'9' ':' '<' '>' '?' '@' + 'A'-'Z' '[' ']' '^' '_' 'a'-'z' '{' '|' '}' '~']+ as s + {INDVAR s} + | '@' + ['!' '$' '%' '&' '*' '+' '-' '.' '/' '0'-'9' ':' '<' '>' '?' '@' + 'A'-'Z' '[' ']' '^' '_' 'a'-'z' '{' '|' '}' '~']+ as s + {SEQVAR s} + | eof { EOF } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-19 00:42:39
|
Revision: 1256 http://toss.svn.sourceforge.net/toss/?rev=1256&view=rev Author: lukstafi Date: 2010-12-19 00:42:33 +0000 (Sun, 19 Dec 2010) Log Message: ----------- GDL parser: initial commit. Modified Paths: -------------- trunk/Toss/Play/Game.ml trunk/Toss/Play/GameTest.ml trunk/Toss/Play/Server.ml Modified: trunk/Toss/Play/Game.ml =================================================================== --- trunk/Toss/Play/Game.ml 2010-12-19 00:33:43 UTC (rev 1255) +++ trunk/Toss/Play/Game.ml 2010-12-19 00:42:33 UTC (rev 1256) @@ -961,13 +961,17 @@ match res with | Aux.Left (_,_,_,state) -> (* {{{ log entry *) - if !debug_level > 5 || (!debug_level > 1 && set_timer <> None) then printf "step-state:\n%s\n%!" (Structure.str state.game_state.struc); - (* }}} *) play ~grid_size ?set_timer ?horizon ~plys:(plys+1) play_def state - | Aux.Right payoff -> state.game_state.struc, discount plys payoff + | Aux.Right payoff -> + (* {{{ log entry *) + if !debug_level > 5 || (!debug_level > 1 && set_timer <> None) then + printf "payoff-state:\n%a\n%!" + (Aux.array_fprint (fun f pv->fprintf f "%F" pv)) payoff; + (* }}} *) + state.game_state.struc, discount plys payoff (* Walk up the tree selecting the optimal estimates route, and update Modified: trunk/Toss/Play/GameTest.ml =================================================================== --- trunk/Toss/Play/GameTest.ml 2010-12-19 00:33:43 UTC (rev 1255) +++ trunk/Toss/Play/GameTest.ml 2010-12-19 00:42:33 UTC (rev 1256) @@ -151,9 +151,9 @@ data = []; } -let update_game (adv_ratio, game) state cur_loc = +let update_game (horizon, adv_ratio, game) state cur_loc = let state = struc_of_str state in - adv_ratio, {game with Arena.struc = state; cur_loc = cur_loc} + horizon, adv_ratio, {game with Arena.struc = state; cur_loc = cur_loc} let rec binary_to_assoc = function @@ -222,7 +222,7 @@ (* board_game ?(zero_sum=true) init_board ?rule_model rules1 rules2 ?payoffs win1 win2 *) let breakthrough_game = - 2.0, board_game + None, 2.0, board_game "[ | | ] \" ... ... ... ... B B..B B..B B..B B.. @@ -322,7 +322,7 @@ "ex x (B(x) and not ex y C(y, x))" let tictactoe_game = - 4.0, board_game + None, 4.0, board_game "[ | P:1 { }; Q:1 { } | ] \" . . . @@ -350,7 +350,7 @@ winPxyz winQxyz let gomoku8x8_game = - 4.0, board_game + None, 4.0, board_game "[ | P:1 { }; Q:1 { } | ] \" ... ... ... ... ... ... ... ... @@ -388,7 +388,7 @@ winPvwxyz winQvwxyz let gomoku19x19_game = - 4.0, board_game + None, 4.0, board_game "[ | P:1 { }; Q:1 { } | ] \" ....................................................... @@ -468,7 +468,7 @@ breakthrough_heur_adv 1.5 let chess_game = - lazy (2.0, state_of_file "./examples/Chess.toss") + lazy (Some 400, 2.0, state_of_file "./examples/Chess.toss") let chess_piece_value_heur = let white_val = @@ -519,9 +519,9 @@ (float_of_int !hist >= float_of_int n *. 0.7) let compute_try search_method randomize effort timer_sec - (heur_adv_ratio, state) loc msg pred = + (horizon, heur_adv_ratio, state) loc msg pred = let p,ps = Game.initialize_default - state ~heur_adv_ratio ~loc ~effort ~search_method () in + state ~heur_adv_ratio ?horizon ~loc ~effort ~search_method () in let old_signal = Sys.signal Sys.sigalrm (Sys.Signal_handle (fun _ -> failwith "timeout")) in @@ -564,7 +564,8 @@ "play: breakthrough suggest in game" >:: (fun () -> - let state = update_game breakthrough_game + let horizon, heur_adv_ratio, state = + update_game breakthrough_game "[ | | ] \" ... ... ... ... ... ... ... ... @@ -584,8 +585,8 @@ ... ... ... ... \"" 1 in (* Game.set_debug_level 5; *) - let move_opt = (let p,ps = Game.initialize_default (snd state) - ~heur_adv_ratio:(fst state) + let move_opt = (let p,ps = Game.initialize_default state + ~heur_adv_ratio ?horizon ~loc:1 ~effort:5 ~heuristic:breakthrough_heur ~search_method:"uct_greedy_playouts" () in @@ -596,9 +597,10 @@ "play: chess suggest first move" >:: (fun () -> - let state = Lazy.force chess_game in - let move_opt = (let p,ps = Game.initialize_default (snd state) - ~heur_adv_ratio:(fst state) + let horizon, heur_adv_ratio, state = + Lazy.force chess_game in + let move_opt = (let p,ps = Game.initialize_default state + ~heur_adv_ratio ?horizon ~loc:0 ~effort:1 ~search_method:"alpha_beta_ord" () in Game.suggest p ps) in @@ -608,7 +610,7 @@ "play: chess random play" >:: (fun () -> - let (heur_adv_ratio, state) = + let horizon, heur_adv_ratio, state = Lazy.force chess_game in let struc = state.Arena.struc in let game = state.Arena.game in @@ -619,7 +621,7 @@ let init_state = Game.initial_state play struc in (* let endstate,payoff = *) ignore (Game.play ~grid_size:Game.cGRID_SIZE - ~set_timer:360 ~horizon:30 play init_state) (* in *) + ~set_timer:360 ?horizon play init_state) (* in *) (* nothing to assert -- just check halting without exceptions *) (* Printf.printf "Chess random play horizon=30 ended in:\n%s\n%!" @@ -629,7 +631,8 @@ "breakthrough payoff" >:: (fun () -> - let state = update_game breakthrough_game + let horizon, heur_adv_ratio, state = + update_game breakthrough_game "[ | | ] \" ... ... ... ... B ...B ...B B..B B.. @@ -649,19 +652,18 @@ W..B W..W W..W W..W \"" 0 in (* Game.set_debug_level 5; *) - let move_opt = (let p,ps = Game.initialize_default (snd state) - ~heur_adv_ratio:(fst state) + let move_opt = (let p,ps = Game.initialize_default state + ~heur_adv_ratio ?horizon ~loc:0 ~effort:2 ~heuristic:breakthrough_heur ~search_method:"alpha_beta_ord" () in Game.toss ~grid_size:Game.cGRID_SIZE p ps) in assert_equal ~msg:"black wins: suggest" ~printer:(function | Aux.Left (bpos, moves, _, _) -> - "game not over: "^move_gs_str (snd state) moves.(bpos) + "game not over: "^move_gs_str state moves.(bpos) | Aux.Right poffs -> Printf.sprintf "{W: %F; B: %F}" poffs.(0) poffs.(1)) (Aux.Right [| -1.0; 1.0 |]) move_opt; - let state = snd state in let payoffs = Array.to_list (Array.mapi (fun i v->string_of_int i,v) state.Arena.game.Arena.graph.(state.Arena.cur_loc).Arena.payoffs_pp) @@ -678,7 +680,8 @@ "chess draw" >:: (fun () -> - let state = update_game (Lazy.force chess_game) + let horizon, heur_adv_ratio, state = + update_game (Lazy.force chess_game) "[a1, b1, c1, d1, e1, f1, g1, h1, a2, b2, c2, d2, e2, f2, g2, h2, a3, b3, c3, d3, e3, f3, g3, h3, a4, b4, c4, d4, e4, f4, g4, h4, a5, b5, c5, d5, e5, f5, g5, h5, a6, b6, c6, d6, e6, f6, g6, h6, a7, b7, c7, d7, e7, f7, g7, h7, a8, b8, c8, d8, e8, f8, g8, h8 | D1 {(a1, b2); (b1, c2); (c1, d2); (d1, e2); (e1, f2); (f1, g2); (g1, h2); (a2, b3); (b2, a1); (b2, c3); (c2, b1); (c2, d3); (d2, c1); (d2, e3); (e2, d1); (e2, f3); (f2, e1); (f2, g3); (g2, f1); (g2, h3); (h2, g1); (a3, b4); (b3, a2); (b3, c4); (c3, b2); (c3, d4); (d3, c2); (d3, e4); (e3, d2); (e3, f4); (f3, e2); (f3, g4); (g3, f2); (g3, h4); (h3, g2); (a4, b5); (b4, a3); (b4, c5); (c4, b3); (c4, d5); (d4, c3); (d4, e5); (e4, d3); (e4, f5); (f4, e3); (f4, g5); (g4, f3); (g4, h5); (h4, g3); (a5, b6); (b5, a4); (b5, c6); (c5, b4); (c5, d6); (d5, c4); (d5, e6); (e5, d4); (e5, f6); (f5, e4); (f5, g6); (g5, f4); (g5, h6); (h5, g4); (a6, b7); (b6, a5); (b6, c7); (c6, b5); (c6, d7); (d6, c5); (d6, e7); (e6, d5); (e6, f7); (f6, e5); (f6, g7); (g6, f5); (g6, h7); (h6, g5); (a7, b8); (b7, a6); (b7, c8); (c7, b6); (c7, d8); (d7, c6); (d7, e8); (e7, d6); (e7, f8); (f7, e6); (f7, g8); (g7, f6); (g7, h8); (h7, g6); (b8, a7); (c8, b7); (d8, c7); (e8, d7); (f8, e7); (g8, f7); (h8, g7)}; D2 {(b1, a2); (c1, b2); (d1, c2); (e1, d2); (f1, e2); (g1, f2); (h1, g2); (a2, b1); (b2, c1); (b2, a3); (c2, d1); (c2, b3); (d2, e1); (d2, c3); (e2, f1); (e2, d3); (f2, g1); (f2, e3); (g2, h1); (g2, f3); (h2, g3); (a3, b2); (b3, c2); (b3, a4); (c3, d2); (c3, b4); (d3, e2); (d3, c4); (e3, f2); (e3, d4); (f3, g2); (f3, e4); (g3, h2); (g3, f4); (h3, g4); (a4, b3); (b4, c3); (b4, a5); (c4, d3); (c4, b5); (d4, e3); (d4, c5); (e4, f3); (e4, d5); (f4, g3); (f4, e5); (g4, h3); (g4, f5); (h4, g5); (a5, b4); (b5, c4); (b5, a6); (c5, d4); (c5, b6); (d5, e4); (d5, c6); (e5, f4); (e5, d6); (f5, g4); (f5, e6); (g5, h4); (g5, f6); (h5, g6); (a6, b5); (b6, c5); (b6, a7); (c6, d5); (c6, b7); (d6, e5); (d6, c7); (e6, f5); (e6, d7); (f6, g5); (f6, e7); (g6, h5); (g6, f7); (h6, g7); (a7, b6); (b7, c6); (b7, a8); (c7, d6); (c7, b8); (d7, e6); (d7, c8); (e7, f6); (e7, d8); (f7, g6); (f7, e8); (g7, h6); (g7, f8); (h7, g8); (a8, b7); (b8, c7); (c8, d7); (d8, e7); (e8, f7); (f8, g7); (g8, h7)}; bB:1 {}; wB:1 {}; wN:1 {}; wP:1 {}; wQ:1 {}; wR:1 {} | ] \" ... ... ... ... ... ... +bN ... @@ -698,7 +701,6 @@ ... ... ... ... \"" 0 in - let heur_adv_ratio, state = state in let payoffs = Array.to_list (Array.mapi (fun i v->string_of_int i,v) state.Arena.game.Arena.graph.(state.Arena.cur_loc).Arena.payoffs_pp) @@ -712,7 +714,7 @@ "0: 0., 1: 0." answ; let move_opt = (let p,ps = Game.initialize_default state - ~heur_adv_ratio + ~heur_adv_ratio ?horizon ~loc:0 ~effort:1 ~search_method:"alpha_beta_ord" () in Game.toss ~grid_size:Game.cGRID_SIZE p ps) in @@ -726,7 +728,8 @@ "matching: breakthrough suggest start" >:: (fun () -> - let (_,state) = breakthrough_game in + let horizon, heur_adv_ratio, state = + breakthrough_game in let r = List.assoc "1" state.Arena.game.Arena.rules in let matches = ContinuousRule.matches state.Arena.struc r in assert_bool "Move to the left should be possible." @@ -735,10 +738,11 @@ "gomoku8x8 suggest" >:: (fun () -> - let state = gomoku8x8_game in + let horizon, heur_adv_ratio, state = + gomoku8x8_game in (* Game.set_debug_level 2; *) - let move_opt = (let p,ps = Game.initialize_default (snd state) - ~heur_adv_ratio:(fst state) ~loc:0 ~effort:2 + let move_opt = (let p,ps = Game.initialize_default state + ~heur_adv_ratio ?horizon ~loc:0 ~effort:2 ~search_method:"alpha_beta_ord" () in Game.suggest p ps) in assert_bool "Game is not over yet -- some move expected." @@ -1138,38 +1142,44 @@ let experiments = "Game" >::: [ "ChessExperiment" >:: (fun () -> - let (heur_adv_ratio, state) = + let (horizon, heur_adv_ratio, state) = Lazy.force chess_game in let struc = state.Arena.struc in let game = state.Arena.game in (* TODO: default_heuristic redoes payoff normalization. *) + (* default_treesearch uses horizon, but default_maximax doesn't *) let play = {Game.game = game; agents= [| Game.default_maximax state.Arena.struc ~depth:1 - ~heur_adv_ratio + ~heuristic:chess_piece_value_heur ~heur_adv_ratio ~pruning:true ~reorder:true game; - Game.default_maximax state.Arena.struc ~depth:1 + Game.default_maximax state.Arena.struc ~depth:2 ~heuristic:chess_piece_value_heur ~heur_adv_ratio ~pruning:true ~reorder:true game; |]; delta = 2.0} in (* FIXME: give/calc delta *) let init_state = Game.initial_state play struc in Game.set_debug_level 2; - let wins = ref 0 in - Printf.printf "Chess experiment -- white: default heuristic, black: chess piece value heuristic.\n%!"; - let n = 5 in + let winsW = ref 0 in + let winsB = ref 0 in + Printf.printf "Chess experiment -- chess piece value heuristic: white: depth 1, black: depth 2.\n%!"; + let n = 40 in for i = 1 to n do Printf.printf "Experiment: Game nr %d of %d\n%!" i n; let _,payoff = - Game.play ~grid_size:Game.cGRID_SIZE ~set_timer:3600 play init_state in - if payoff.(0) > 0.0 then incr wins; - Printf.printf "\n%d wins out of %d trials\n%!" !wins i + Game.play ~grid_size:Game.cGRID_SIZE ~set_timer:3600 + ?horizon play init_state in + if payoff.(0) > 0.0 then incr winsW; + if payoff.(1) > 0.0 then incr winsB; + Printf.printf + "\nWhite %d wins, Black %d wins out of %d trials\n%!" + !winsW !winsB i done; assert_bool - (Printf.sprintf "Hypothesis: -- wronged %d out of %d trials." - (n - !wins) n) - (!wins > 2) + (Printf.sprintf "Hypothesis: -- wronged %d out of %d trials in %d plays." + (!winsB - !winsW) (!winsB + !winsW) n) + (!winsW > !winsB) ); ] @@ -1178,12 +1188,7 @@ let a () = run_test_tt ~verbose:true experiments - -(* The same content as in .toss files. *) let a () = - print_endline ("\n" ^ Arena.sprint_state (snd (Lazy.force chess_game))) - -let a () = Game.set_debug_level 3 let a () = Modified: trunk/Toss/Play/Server.ml =================================================================== --- trunk/Toss/Play/Server.ml 2010-12-19 00:33:43 UTC (rev 1255) +++ trunk/Toss/Play/Server.ml 2010-12-19 00:42:33 UTC (rev 1256) @@ -53,7 +53,20 @@ done let req_of_str s = - ArenaParser.parse_request Lexer.lex (Lexing.from_string s) + let http_beg = "POST / HTTP/" in + let http_beg_l = String.length http_beg in + let s_len = String.length s in + if s_len > http_beg_l && String.sub s 0 http_beg_l = http_beg + then + if Str.string_match (Str.regexp "\r?\n\r?\n") s 0 + then + let m_beg = Str.match_end () in + Aux.Right (GDLParser.parse_request KIFLexer.lex + (Lexing.from_string (String.sub s m_beg (s_len-m_beg)))) + else + raise (Lexer.Parsing_error "Empty HTTP message") + else + Aux.Left (ArenaParser.parse_request Lexer.lex (Lexing.from_string s)) let rec read_in_line in_ch = let line_in = input_line in_ch in @@ -128,8 +141,9 @@ let req = req_of_str line in let resp = match req with - | Arena.SuggestLocMoves (loc, timer, effort, how, horizon, heuristic, - heur_adv_ratio) -> ( + | Aux.Left (Arena.SuggestLocMoves + (loc, timer, effort, how, horizon, heuristic, + heur_adv_ratio)) -> ( Random.self_init (); (* TODO: should be in idle time, not now *) Gc.full_major (); @@ -159,7 +173,7 @@ Game.move_gs_str !state move | None -> "None" ) - | Arena.ApplyRule (r_name, mtch, t, p) -> ( + | Aux.Left (Arena.ApplyRule (r_name, mtch, t, p) as req) -> ( if !game_modified then let (new_state, resp) = Arena.handle_request !state req in state := new_state; resp @@ -228,11 +242,14 @@ }; resp ) - | _ -> + | Aux.Left req -> game_modified := !game_modified || possibly_modifies_game req; let (new_state, resp) = Arena.handle_request !state req in - state := new_state; resp in + state := new_state; resp + | Aux.Right req -> + failwith "GDL request parsed but handler not implemented yet" + in if !debug_level > 0 then print_endline ("Repl: " ^ resp ^ "\n"); output_string out_ch (resp ^ "\n"); flush out_ch; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-19 00:33:50
|
Revision: 1255 http://toss.svn.sourceforge.net/toss/?rev=1255&view=rev Author: lukaszkaiser Date: 2010-12-19 00:33:43 +0000 (Sun, 19 Dec 2010) Log Message: ----------- WebClient work. Modified Paths: -------------- trunk/Toss/WebClient/Handler.py trunk/Toss/WebClient/Login.js trunk/Toss/WebClient/Main.js trunk/Toss/WebClient/README trunk/Toss/WebClient/Style.css trunk/Toss/WebClient/index.html trunk/Toss/WebClient/make_db.py trunk/Toss/WebClient/register.html Added Paths: ----------- trunk/Toss/WebClient/profile.html Modified: trunk/Toss/WebClient/Handler.py =================================================================== --- trunk/Toss/WebClient/Handler.py 2010-12-18 17:49:52 UTC (rev 1254) +++ trunk/Toss/WebClient/Handler.py 2010-12-19 00:33:43 UTC (rev 1255) @@ -76,6 +76,10 @@ str(pid) + "_" + str(move)) return (str([play_name (p) for p in plays])) +def list_friends (db, uid): + friends = get_all_from_db (db, "friends", "id='"+ uid + "'") + return (str([str(f) for (_, f) in friends])) + def db_cur_insert (db, game, p1, p2, pid, move, toss, info, svg_str): db.execute ("insert into cur_states(playid, game, player1, player2, move, toss, info, svg) values (?, ?, ?, ?, ?, ?, ?, ?)", (pid, game, p1, p2, move, toss, info, svg_str)) @@ -151,13 +155,17 @@ if (pwd1 != pwd2): return "" return (uid) -def login_user (db, req, uid, pwd): +def login_user (db, req, uid, chk, pwd): db_pwd = passwd_from_db (db, uid) if not db_pwd: return ("no such user registered") if (pwd != db_pwd): return ("wrong password") - t = time.time() + 3600; - cookie1 = Cookie.Cookie(TUID + 'username', uid, expires=t) - cookie2 = Cookie.Cookie(TUID + 'passphrase', pwd, expires=t) + t = time.time() + 3600000; + if chk == "false": + cookie1 = Cookie.Cookie(TUID + 'username', uid) + cookie2 = Cookie.Cookie(TUID + 'passphrase', pwd) + else: + cookie1 = Cookie.Cookie(TUID + 'username', uid, expires=t) + cookie2 = Cookie.Cookie(TUID + 'passphrase', pwd, expires=t) Cookie.add_cookie(req, cookie1) Cookie.add_cookie(req, cookie2) return ("OK") @@ -171,6 +179,45 @@ db.commit () return (True) +def add_opponent (db, uid, oppid): + if uid == "": return ("You must login first to add opponents.") + if get_user_name (db, oppid) == "": + return ("No such opponent found among tPlay users.") + db.execute ("insert into friends(id, fid) values (?, ?)", (uid, oppid)) + db.commit () + return ("OK") + +def get_user_name (db, uname): + res = get_all_from_db (db, "users", "id='" + uname + "'") + if len(res) > 1: raise Exception ("db", "many entries for " + uname) + if len(res) == 0: return ("") + (_, name, _, _, _) = res[0] + return (name) + +def get_user_surname (db, uname): + res = get_all_from_db (db, "users", "id='" + uname + "'") + if len(res) > 1: raise Exception ("db", "many entries for " + uname) + if len(res) == 0: return ("") + (_, _, surname, _, _) = res[0] + return (surname) + +def get_user_mail (db, uname): + res = get_all_from_db (db, "users", "id='" + uname + "'") + if len(res) > 1: raise Exception ("db", "many entries for " + uname) + if len(res) == 0: return ("") + (_, _, _, email, _) = res[0] + return (email) + +def change_user_data (db, uid, udata): + if uid == "": return ("You must login first to change data.") + if len(udata) != 3: return ("Internal error, data not changed.") + uid_s = "id='" + uid + "'" + db.execute ("update users set name='" + udata[0] + "' where " + uid_s) + db.execute ("update users set surname='" + udata[1] + "' where " + uid_s) + db.execute ("update users set email='" + udata[2] + "' where " + uid_s) + db.commit () + return ("OK") + def get_free_id (db): fid = 0 for f in db.execute ("select count(*) from cur_states"): @@ -196,22 +243,44 @@ "\nPlease choose another username and try again.") return apache.OK if cmd == "LOGIN": - uname, sep, pwd = data.partition(' ') - res = login_user (db, req, uname, pwd) - if res == "OK": - req.write("OK") - return apache.OK - req.write("Login failed for " + uname + ": " + res) + ui = data.split("$") + res = "internal error" + if len(ui) == 3: + res = login_user (db, req, ui[0], ui[1], ui[2]) + if res == "OK": + req.write("OK") + return apache.OK + req.write("Login failed for " + ui[0] + ": " + res) return apache.OK if cmd == "LOGOUT": - cookie = Cookie.Cookie(TUID + 'passphrase', "a") - cookie = Cookie.Cookie(TUID + 'username', "a") - Cookie.add_cookie(req, cookie) - req.write ("user logged out: " + usr + ".") + cookie1 = Cookie.Cookie(TUID + 'passphrase', "a") + cookie2 = Cookie.Cookie(TUID + 'username', "a") + Cookie.add_cookie(req, cookie1) + Cookie.add_cookie(req, cookie2) + req.write ("User logged out: " + usr + ".") return apache.OK if cmd == "FREEID": req.write(str(get_free_id (db))) return apache.OK + if cmd == "ADDOPP": + req.write(str(add_opponent (db, usr, data))) + return apache.OK + if cmd == "GET_NAME": + req.write(str(get_user_name (db, data))) + return apache.OK + if cmd == "GET_SURNAME": + req.write(str(get_user_surname (db, data))) + return apache.OK + if cmd == "LIST_FRIENDS": + req.write(str(list_friends (db, usr))) + return apache.OK + if cmd == "GET_MAIL": + if usr == "": return ("You must login first to get email data.") + req.write(str(get_user_mail (db, data))) + return apache.OK + if cmd == "CHANGEUSR": + req.write(str(change_user_data (db, usr, data.split("$")))) + return apache.OK if (cmd == "LIST_PLAYS") or (cmd == "OPEN_DB") or (cmd == "UPD_SVG"): res = eval (cmd.lower() + "(db, " + data + ")") req.write(str(res)) Modified: trunk/Toss/WebClient/Login.js =================================================================== --- trunk/Toss/WebClient/Login.js 2010-12-18 17:49:52 UTC (rev 1254) +++ trunk/Toss/WebClient/Login.js 2010-12-19 00:33:43 UTC (rev 1255) @@ -14,7 +14,7 @@ // Setup a user function setup_user (un) { UNAME = un - document.getElementById("topuser").innerHTML = "Welcome " + un; + document.getElementById("topuser").innerHTML = "Welcome " + disp_name(un); document.getElementById("loginform").style.display = "none"; document.getElementById("topright-register").style.display = "none"; document.getElementById("topright").style.display = "inline"; @@ -25,6 +25,7 @@ list_plays ("Entanglement"); list_plays ("Gomoku"); list_plays ("Tic-Tac-Toe"); + get_opponents (); } // Clear view @@ -49,13 +50,40 @@ } } +// Onload handler for the profile page +function startup_profile () { + var un = srv("USERNAME", "user"); + if (un != "") { + UNAME = un + document.getElementById("topuser").innerHTML = + "Welcome " + disp_name(un); + document.getElementById("loginform").style.display = "none"; + document.getElementById("topright-register").style.display = "none"; + document.getElementById("topright").style.display = "inline"; + document.getElementById("welcome").style.display = "none"; + document.getElementById("main-profile").style.display = "block"; + document.getElementById('name').value = srv("GET_NAME", un); + document.getElementById('surname').value = srv("GET_SURNAME", un); + document.getElementById('email').value = srv("GET_MAIL", un); + get_opponents (); + var o = document.getElementById("opponents-list"); + for (var i = 0; i < FRIENDS.length; i++) { + var li = document.createElement('li'); + li.innerHTML = disp_name(FRIENDS[i]) + " (" + FRIENDS[i] + ")"; + o.appendChild (li); + } + }; +} + // Login function login () { un = document.getElementById('username').value; pwd = document.getElementById('password').value; - resp = sync_server_msg ("LOGIN#" + un + " " + crypt(TSALT + pwd)); + chk = "false"; + if (document.getElementById('remember').checked) { chk = "true" }; + resp = sync_server_msg ("LOGIN#" + un +"$"+ chk +"$"+ crypt(TSALT + pwd)); if (resp == "OK") { - setup_user (un) + window.location.reload () } else { alert (resp) } @@ -64,8 +92,21 @@ // Logout function logout () { clear_view (); + resp = sync_server_msg ("LOGOUT#user"); + return; } +function logout_profile () { + document.getElementById("loginform").style.display = "inline"; + document.getElementById("topright-register").style.display = "inline"; + document.getElementById("topright").style.display = "none"; + document.getElementById("topuser").innerHTML = ""; + document.getElementById("main-profile").style.display = "none"; + document.getElementById("welcome").style.display = "block"; + resp = sync_server_msg ("LOGOUT#user"); + return; +} + // Register new user function register () { un = document.getElementById('username').value; @@ -111,3 +152,38 @@ resp = sync_server_msg ("REGISTER#" + data + "$" + crypt(TSALT + pwd)); alert (resp); } + +// Change user data +function change_profile () { + name = document.getElementById('name').value; + surname = document.getElementById('surname').value; + email = document.getElementById('email').value; + if (name == "") { + alert ("Your name was not given and it is necessary." + CORRMSG); + return; + } + if (surname == "") { + alert ("Your surname was not given and it is necessary." + CORRMSG); + return; + } + if (email.indexOf("@") < 1 || email.indexOf(".") < 1) { + alert ("Please provide a valid email address."); + return; + } + if (name.indexOf ("$") > 0 || surname.indexOf ("$") > 0 || + email.indexOf ("$") > 0) { + alert ("Your data must not contain $, i.e. the dolar sign." + CORRMSG); + return; + } + resp = sync_server_msg ("CHANGEUSR#" + name + "$" + surname + "$" + email); + if (resp != "OK") { alert(resp); } + window.location.reload (); +} + +// Add opponent for the current user. +function add_opponent () { + oppuname = document.getElementById('oppuname').value; + resp = sync_server_msg ("ADDOPP#" + oppuname); + if (resp != "OK") { alert(resp); } + window.location.reload (); +} \ No newline at end of file Modified: trunk/Toss/WebClient/Main.js =================================================================== --- trunk/Toss/WebClient/Main.js 2010-12-18 17:49:52 UTC (rev 1254) +++ trunk/Toss/WebClient/Main.js 2010-12-19 00:33:43 UTC (rev 1255) @@ -8,6 +8,7 @@ var CUR_PLAY_I = -1; var FRIENDS = [] +var UNAME_TO_NAME_MAP = {} var MAX_OPNT_LEN = 20; var FULL_OPNT_LEN = 0; @@ -114,15 +115,23 @@ PLAYS[i][1] + "', '" + PLAYS[i][2] + "', '" + PLAYS[i][3] + "'") } +function disp_name (uname) { + if (UNAME_TO_NAME_MAP[uname]) { return (UNAME_TO_NAME_MAP[uname]); } + name = srv ("GET_NAME", uname); + UNAME_TO_NAME_MAP[uname] = name; + return (name); +} + function new_play_item (game, i) { var li = document.createElement('li'); li.setAttribute ("class", "plays-list-elem"); li.setAttribute ("id", "plays-list-" + game + "-elem-" + i); var p = PLAYS[i][2]; - li.innerHTML = "" + PLAYS[i][2] + ': ' + PLAYS[i][0] + " vs " + - PLAYS[i][1] + " " + //" move " + PLAYS[i][3] + " "+ - '<a title="Open" href="#" onclick="'+ "play_click('"+ game + "', " + p + - ", " + i + ')">Open</a>'; + var bs = '<button class="bt" title="Open" onclick="'+ "play_click('" + + game + "', " + p + ", " + i + ')">Open</button> '; + li.innerHTML = bs + disp_name(PLAYS[i][0]) +" vs " + + disp_name(PLAYS[i][1])+ " (game " + PLAYS[i][2] + ')' + // +'<a href="#" onclick="'+ "del_play('"+ fn + "')" + '">Delete</a>'; return (li); } @@ -169,7 +178,7 @@ CUR_PLAY_I = pi; VIEW_MIRROR = (PLAYS[CUR_PLAY_I][0] == UNAME) ? 0 : 1; document.getElementById("cur-player").innerHTML = - PLAYS[CUR_PLAY_I][PLAYS[CUR_PLAY_I][3] % 2]; + disp_name(PLAYS[CUR_PLAY_I][PLAYS[CUR_PLAY_I][3] % 2]); toss_open_db (play_py_id(pi)); full_redraw (); } @@ -190,7 +199,7 @@ CUR_ELEMS = []; ELEM_COUNTERS = {}; document.getElementById("cur-player").innerHTML = - PLAYS[CUR_PLAY_I][(m + 1) % 2]; + disp_name(PLAYS[CUR_PLAY_I][(m + 1) % 2]); document.getElementById('cur-move').innerHTML = "none"; full_redraw (); PLAYS[CUR_PLAY_I][3] = parseInt(PLAYS[CUR_PLAY_I][3]) + 1; @@ -205,19 +214,13 @@ alert ("Deleting " + play); } -function store_friend_names () { - for (var i = 0; i < FRIENDS.length; i++) { - ID_TO_USER_MAP[FRIENDS[i].id] = FRIENDS[i].name; - ID_TO_USER_FNAME_MAP[FRIENDS[i].id] = FRIENDS[i].first_name; - } -} - -function opponent_item (data, index) { +function opponent_item (uid, index) { var li = document.createElement('li'); li.setAttribute ("class", "opponents-list-elem"); - li.setAttribute ("id", "opponent-" + data.id + "-" + index); - li.innerHTML = '<a href="#" onclick="new_play_do(' + data.id + ')">' + - data.name + '</a>'; + li.setAttribute ("id", "opponent-" + uid); // + "-" + index + li.innerHTML = + '<button class="dbt" onclick="new_play_do(' + "'" + uid + "'" + ')">' + + disp_name(uid) + ' (' + uid + ') </button>'; return (li); } @@ -238,7 +241,8 @@ var zeroli = document.createElement('li'); zeroli.setAttribute ("class", "opponents-list-elem"); zeroli.setAttribute ("id", "opponent-" + "-0"); - zeroli.innerHTML = '<a href="#" onclick="new_play_do(-1)">Play against Yourself</a>'; + zeroli.innerHTML = '<button class="dbt" onclick="new_play_do(-1)">' + + 'Play against Yourself</button>'; o.appendChild (zeroli); for (var i = 0; i < FRIENDS.length; i++) { var oi = opponent_item (FRIENDS[i], i+1); @@ -306,7 +310,7 @@ document.getElementById("play-number").innerHTML = "" + FREE_PLAY_NO; CUR_PLAY_I = PLAYS.length; VIEW_MIRROR = 0; - document.getElementById("cur-player").innerHTML = UNAME; + document.getElementById("cur-player").innerHTML = disp_name(UNAME); document.getElementById("game-disp").style.display = "block"; document.getElementById("plays").style.left = "30em"; var p = [UNAME, opp_uid, FREE_PLAY_NO, 0]; @@ -319,3 +323,8 @@ li = new_play_item (GAME_NAME, CUR_PLAY_I); document.getElementById("plays-list-" + GAME_NAME).appendChild(li); } + +function get_opponents () { + var lst = srv ("LIST_FRIENDS", "user"); + FRIENDS = convert_python_list (',', lst); +} \ No newline at end of file Modified: trunk/Toss/WebClient/README =================================================================== --- trunk/Toss/WebClient/README 2010-12-18 17:49:52 UTC (rev 1254) +++ trunk/Toss/WebClient/README 2010-12-19 00:33:43 UTC (rev 1255) @@ -19,8 +19,8 @@ TODO: - - use name in interface, try buttons, add oponents table and adding page - move interface: first click all, second click toggle, if one - confirm msg + - move suggestions and play against computer - after the above: remove left-of-board div, confirm in the middle - after the above: show game result in the middle / instead of move - sort plays by who's turn it is Modified: trunk/Toss/WebClient/Style.css =================================================================== --- trunk/Toss/WebClient/Style.css 2010-12-18 17:49:52 UTC (rev 1254) +++ trunk/Toss/WebClient/Style.css 2010-12-19 00:33:43 UTC (rev 1255) @@ -11,12 +11,146 @@ height: 100%; } +.bt { + border-color: #260314; + border-radius: 4px; + border-width: 1px; + color: #260314; + background-color: #ffe4aa; + font-size: 0.9em; + font-family: Verdana, 'TeXGyreHerosRegular', sans; +} + +.bt:hover { + cursor: pointer; + text-decoration: underline; +} + +#plays .bt { + width: 7em; + position: absolute; + right: 0px; +} + +.dbt { + border-color: #ffe4aa; + border-radius: 4px; + border-width: 0px; + color: #ffe4aa; + background-color: #400827; + font-size: 0.9em; + font-family: Verdana, 'TeXGyreHerosRegular', sans; +} + +.dbt:hover { + cursor: pointer; + text-decoration: underline; +} + .reglabel { float: left; clear: left; - width: 10em; + width: 12em; + margin-top: 0.3em; } +.loginsmall { + position: relative; + top: 1px; + font-size: 0.6em; + margin: 0px; + padding: 0px; +} + +.loginchk { + font-size: 0.6em; + margin: 0px; + padding: 0px; +} + +.loginput { + border-color: #ffe4aa; + border-radius: 4px; + border-width: 1px; + position: relative; + top: 2px; +} + +.forminput { + border-color: #ffe4aa; + border-radius: 4px; + border-width: 2px; + position: relative; + top: 2px; +} + +#remember { + margin: 0px; + padding: 0px; + position: absolute; + top: -2px; + left: -1em; +} + +#rememberspan { + margin: 0px; + padding: 0px; + position: relative; + top: -2px; +} + +#loginbt { + position: relative; + top: -2px; + font-weight: bold; + font-family: Verdana, 'TeXGyreHerosRegular', sans; + color: #400827; + background-color: #ffffff; + border-color: #ffe4aa; + border-radius: 4px; + border-width: 1px; +} + +#loginbt:hover { + cursor: pointer; +} + +#logoutbt { + position: relative; + top: -0.2em; + font-family: Verdana, 'TeXGyreHerosRegular', sans; + font-size: 1em; + font-weight: bold; + color: #ffe4aa; + background-color: #400827; + border-color: #ffe4aa; + border-radius: 4px; + border-width: 0px; +} + +#logoutbt:hover { + cursor: pointer; + color: #b5bf8f; +} + +#login1 { + position: absolute; + top: 0px; + left: 10em; +} + +#login2 { + position: absolute; + top: 0px; + left: 20em; +} + +#login3 { + position: absolute; + top: 0.3em; + left: 30em; +} + #logo { font-size: 2em; float: left; @@ -25,13 +159,13 @@ padding-left: 0.25em; } -#logo a, #logo a:link, #logo a:active, #logo a:visited { +#top a, #logo a:link, #logo a:active, #logo a:visited { color: #ffe4aa; background-color: transparent; text-decoration: none; } -#logo a:hover { +#top a:hover { color: #b5bf8f; } @@ -62,13 +196,17 @@ } #topright { - float: right; + position: absolute; + top: 0.7em; + right: 1em; margin-right: 0em; display: none; } #topright-register { - float: right; + position: absolute; + top: 0.7em; + right: 1em; margin-right: 0em; } @@ -136,19 +274,19 @@ #main a, #main a:link, #main a:active, #main a:visited { color: #260314; - text-decoration: underline; + text-decoration: none; } #main a:hover { color: #400827; - text-decoration: none; + text-decoration: underline; } #opponents { display: none; position: absolute; - left: 19em; + left: 6em; top: 3.5em; min-width: 20em; color: #ffe4aa; @@ -159,16 +297,6 @@ z-index: 10; } -#opponents a, #opponents a:link, #opponents a:active, #opponents a:visited { - color: #ffe4aa; - text-decoration: none; - font-weight: bold; -} - -#opponents a:hover { - color: #b5bf8f; -} - #opponents-list { list-style: square; margin-top: 0.5em; @@ -178,6 +306,28 @@ /* margin-left: -1em; */ } +#opponents-cancel { + position: absolute; + right: 1em; + top: 1em; + width: 5em; +} + +#opponents-add { + position: absolute; + right: 6.5em; + top: 1.2em; + width: 6em; + border-color: #260314; + border-radius: 4px; + border-width: 1px; + color: #260314; + background-color: #ffe4aa; + font-weight: normal; + text-align: center; + font-size: 0.9em; +} + #opponents-next { position: absolute; right: 1em; @@ -289,18 +439,29 @@ padding-left: 0em; } +.game-par { + padding-top: 2px; + border-top: 2px solid #260314; +} + #plays { + position: absolute; + top: 3em; + left: 3em; + width: 30em; display: none; - padding-left: 1em; } -#plays-list { +.plays-list { + margin-left: 1em; + padding-left: 0px; list-style: none; margin-top: 0.25em; } .plays-list-elem { - margin-left: -1.5em; + margin-left: 0em; + margin-bottom: 0.5em; } .plays-list-elem a { Modified: trunk/Toss/WebClient/index.html =================================================================== --- trunk/Toss/WebClient/index.html 2010-12-18 17:49:52 UTC (rev 1254) +++ trunk/Toss/WebClient/index.html 2010-12-19 00:33:43 UTC (rev 1255) @@ -20,15 +20,30 @@ <div id="topbar"> <span id="topuser"></span> <form id="loginform" style="display: inline;"> -Username: <input type="text" name="username" id="username" /> - -Password: <input type="password" name="password" id="password" - onkeypress="if (window.event && window.event.keyCode == 13) { login () }" /> - -<a id="login" href="#" onclick="login()">Login</a> +<div id="login1"> + <p class="loginsmall">Username:</p> +<input class="loginput" type="text" name="username" id="username" size="15" /> +</div> +<div id="login2"> + <p class="loginsmall">Password:</p> +<input class="loginput" type="password" name="password" id="password" size="15" + onkeypress="if (window.event && window.event.keyCode == 13) { login() }" + /> +</div> +<div id="login3"> + <p class="loginchk"> + <input type="checkbox" id="remember" value="r" + checked="yes"><span id="rememberspan">Remember me</span> + </input> + </p> + <button type="button" id="loginbt" onclick="login()"> + <span id="loginspan">Login</span> + </button> +</div> </form> +</div> <span id="topright"> - <a id="logout" href="#" onclick="logout()">Logout</a> + <button id="logoutbt" onclick="logout()">Logout</button> </span> <span id="topright-register"> <a href="register.html">Register</a> @@ -39,13 +54,19 @@ <div id="main"> <div id="opponents"> - Pick Opponent: (<a href="#" onclick="new_play_do(0)">Cancel</a>) + Pick Opponent: + <a id="opponents-add" href="profile.html" target="_blank" + onclick="window.location.reload()">Find New</a> + <button class="bt" id="opponents-cancel" + onclick="window.location.reload()">Cancel</button> <ul id="opponents-list"></ul> - <a href="#" id="opponents-prev" onclick="opponents_prev()">Prev</a> - <a href="#" id="opponents-next" onclick="opponents_next()">Next</a> + <button class="bt" id="opponents-prev" + onclick="opponents_prev()">Prev</button> + <button class="bt" id="opponents-next" + onclick="opponents_next()">Next</button> </div> -<div id="welcome" class="hyphenate"> +<div id="welcome"> <p id="welcome-top">Enjoy games on <span class="logo-in">tPlay</span></p> <p class="short"> Strategic games are fun! @@ -53,7 +74,7 @@ <span class="logo-in">tPlay</span>!</p> </div> -<div id="nosvg" class="hyphenate short" +<div id="nosvg" style="border: 1px solid #260314; padding-left: 1em; display: none;"> <p style="padding-left: 1.2em; font-size: 1.2em;"<b>SVG Support Missing</b></p> <p>Your browser does not seem to support SVG, @@ -75,35 +96,35 @@ <div id="game-title"></div> <div id="plays"> - <p> + <p class="game-par"> + <button class="bt" onclick="new_play ('Breakthrough')">New Game</button> <a href="http://en.wikipedia.org/wiki/Breakthrough_(board_game)" class="game_list">Breakthrough</a> - (<a href="#" onclick="new_play ('Breakthrough')">New Game</a>) </p> - <ul id="plays-list-Breakthrough"></ul> - <p> + <ul class="plays-list" id="plays-list-Breakthrough"></ul> + <p class="game-par"> + <button class="bt" onclick="new_play ('Chess')">New Game</button> <a class="game_list" href="http://en.wikipedia.org/wiki/Chess">Chess</a> - (<a href="#" onclick="new_play ('Chess')">New Game</a>) </p> - <ul id="plays-list-Chess"></ul> - <p> + <ul class="plays-list" id="plays-list-Chess"></ul> + <p class="game-par"> + <button class="bt" onclick="new_play ('Entanglement')">New Game</button> <a href="http://en.wikipedia.org/wiki/Entanglement_(graph_measure)" class="game_list">Entanglement</a> - (<a href="#" onclick="new_play ('Entanglement')">New Game</a>) </p> - <ul id="plays-list-Entanglement"></ul> - <p> + <ul class="plays-list" id="plays-list-Entanglement"></ul> + <p class="game-par"> + <button class="bt" onclick="new_play ('Gomoku')">New Game</button> <a href="http://en.wikipedia.org/wiki/Gomoku" class="game_list">Gomoku</a> - (<a href="#" onclick="new_play ('Gomoku')">New Game</a>) </p> - <ul id="plays-list-Gomoku"></ul> - <p> + <ul class="plays-list" id="plays-list-Gomoku"></ul> + <p class="game-par"> + <button class="bt" onclick="new_play ('Tic-Tac-Toe')">New Game</button> <a href="http://en.wikipedia.org/wiki/Tic-tac-toe" class="game_list">Tic-Tac-Toe</a> - (<a href="#" onclick="new_play ('Tic-Tac-Toe')">New Game</a>) </p> - <ul id="plays-list-Tic-Tac-Toe"></ul> + <ul class="plays-list" id="plays-list-Tic-Tac-Toe"></ul> </div> @@ -117,7 +138,7 @@ Chosen move:<br/> <div id="cur-move">none</div> <div id="mk-move"> - <a href="#" onclick="make_move ()">Make move</a> + <button class="bt" onclick="make_move ()">Make move</button> </div> </div> <div id="board"><div id="working">Working...</div></div> Modified: trunk/Toss/WebClient/make_db.py =================================================================== --- trunk/Toss/WebClient/make_db.py 2010-12-18 17:49:52 UTC (rev 1254) +++ trunk/Toss/WebClient/make_db.py 2010-12-19 00:33:43 UTC (rev 1255) @@ -14,6 +14,7 @@ conn.execute("create table games(game string primary key, toss string)") conn.execute("create table ports(port int primary key, locked bool)") conn.execute("create table lock(tid int primary key, locked bool)") +conn.execute("create table friends(id string, fid string)") conn.commit () conn.execute ("insert into lock(tid, locked) values (?, ?)", Added: trunk/Toss/WebClient/profile.html =================================================================== --- trunk/Toss/WebClient/profile.html (rev 0) +++ trunk/Toss/WebClient/profile.html 2010-12-19 00:33:43 UTC (rev 1255) @@ -0,0 +1,101 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg" xml:lang="en" lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/xhtml+xml; charset=UTF-8" /> + <title>tPlay — Profile</title> + <meta http-equiv="X-UA-Compatible" content="chrome=1"> + <link rel="icon" type="image/vnd.microsoft.icon" href="/favicon.ico" /> + <link href="fontstyle.css" media="screen" rel="stylesheet" type="text/css" /> + <link rel="stylesheet" type="text/css" href="Style.css" media="screen" title="Default"/> + <script type="text/javascript" src="crypto-sha256.js"> </script> + <script type="text/javascript" src="Connect.js"> </script> + <script type="text/javascript" src="DefaultStyle.js"> </script> + <script type="text/javascript" src="Main.js"> </script> + <script type="text/javascript" src="Login.js"> </script> +</head> + +<body onload="startup_profile()"> +<div id="top"> +<div id="logo"><a href="index.html">tPlay</a></div> +<div id="topbar"> +<span id="topuser"></span> +<form id="loginform" style="display: inline;"> +<div id="login1"> + <p class="loginsmall">Username:</p> +<input class="loginput" type="text" name="username" id="username" size="15" /> +</div> +<div id="login2"> + <p class="loginsmall">Password:</p> +<input class="loginput" type="password" name="password" id="password" size="15" + onkeypress="if (window.event && window.event.keyCode == 13) { login() }" + /> +</div> +<div id="login3"> + <p class="loginchk"> + <input type="checkbox" id="remember" value="r" + checked="yes"><span id="rememberspan">Remember me</span> + </input> + </p> + <button type="button" id="loginbt" onclick="login()"> + <span id="loginspan">Login</span> + </button> +</div> +</form> +</div> +<span id="topright"> + <button id="logoutbt" onclick="logout_profile()">Logout</button> +</span> +<span id="topright-register"> + <a href="register.html">Register</a> +</span> +</div> +</div> + +<div id="main"> + +<div id="welcome"> +<p id="welcome-top">To edit your <span class="logo-in">tPlay</span> + profile please login above or <a href="register.html">register</a> first. +</p> +</div> + +<div id="main-profile" style="display: none;"> +<h2>Your Profile</h2> + +<form id="changeprofileform"> +<p> <span class="reglabel">Name:</span> + <input class="forminput" type="text" name="name" id="name" /> +</p> +<p> <span class="reglabel">Surname:</span> + <input class="forminput" type="text" name="surname" id="surname" /> +</p> +<p> <span class="reglabel">Email:</span> + <input class="forminput" type="text" name="email" id="email" /> +</p> +<button class="bt" id="changebt" type="button" + onclick="change_profile()">Change</button> +</form> + +<h2>Your Opponents</h2> + +<div id="opponents-profile"> + <ul id="opponents-list"></ul> +</div> + +<form id="opponentsform"> +<p> <span class="reglabel">Opponent Username:</span> + <input class="forminput" type="text" name="oppuname" id="oppuname" /> +</p> +<button class="bt" id="oppaddbt" type="button" + onclick="add_opponent()">Add Opponent</button> +</form> +</div> + +</div> + +<div id="bottom"> +<div style="margin-right: 0em; display: none;">Disclaimer</div> +</div> + +</body> +</html> Modified: trunk/Toss/WebClient/register.html =================================================================== --- trunk/Toss/WebClient/register.html 2010-12-18 17:49:52 UTC (rev 1254) +++ trunk/Toss/WebClient/register.html 2010-12-19 00:33:43 UTC (rev 1255) @@ -12,7 +12,7 @@ <script type="text/javascript" src="Login.js"> </script> </head> -<body"> +<body> <div id="top"> <div id="logo"><a href="index.html">tPlay</a></div> </div> @@ -23,23 +23,24 @@ <form id="registerform"> <p> <span class="reglabel">Username:</span> - <input type="text" name="username" id="username" /> </p> + <input class="forminput" type="text" name="username" id="username" /> </p> <p> <span class="reglabel">Password:</span> - <input type="password" name="password" id="password" /> + <input class="forminput" type="password" name="password" id="password" /> </p> <p> <span class="reglabel">Repeat Password:</span> - <input type="password" name="rptpassword" id="rptpassword" /> + <input class="forminput" type="password" name="rptpassword" + id="rptpassword" /> </p> <p> <span class="reglabel">Name:</span> - <input type="text" name="name" id="name" /> + <input class="forminput" type="text" name="name" id="name" /> </p> <p> <span class="reglabel">Surname:</span> - <input type="text" name="surname" id="surname" /> + <input class="forminput" type="text" name="surname" id="surname" /> </p> <p> <span class="reglabel">Email:</span> - <input type="text" name="email" id="email" /> + <input class="forminput" type="text" name="email" id="email" /> </p> -<button id="registerbt" type="button" onclick="register()">Register</button> +<button class="bt" id="registerbt" type="button" onclick="register()">Register</button> </form> </div> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-18 17:50:00
|
Revision: 1254 http://toss.svn.sourceforge.net/toss/?rev=1254&view=rev Author: lukaszkaiser Date: 2010-12-18 17:49:52 +0000 (Sat, 18 Dec 2010) Log Message: ----------- Continue to improve WebClient, order in file names, registration and user table. Modified Paths: -------------- trunk/Toss/WebClient/README trunk/Toss/WebClient/index.html trunk/Toss/WebClient/make_db.py trunk/Toss/WebClient/register.html Added Paths: ----------- trunk/Toss/WebClient/Connect.js trunk/Toss/WebClient/DefaultStyle.js trunk/Toss/WebClient/Handler.py trunk/Toss/WebClient/Login.js trunk/Toss/WebClient/Main.js trunk/Toss/WebClient/Style.css Removed Paths: ------------- trunk/Toss/WebClient/TossConnect.js trunk/Toss/WebClient/TossDefaultStyle.js trunk/Toss/WebClient/TossHandler.py trunk/Toss/WebClient/TossMain.js trunk/Toss/WebClient/TossStyle.css Copied: trunk/Toss/WebClient/Connect.js (from rev 1253, trunk/Toss/WebClient/TossConnect.js) =================================================================== --- trunk/Toss/WebClient/Connect.js (rev 0) +++ trunk/Toss/WebClient/Connect.js 2010-12-18 17:49:52 UTC (rev 1254) @@ -0,0 +1,212 @@ +// JavaScript Toss Module -- Connect (basic Toss Server connection routines) + +var UNAME = ""; + +var MODEL_MAXX = 0.0; +var MODEL_MINX = 0.0; +var MODEL_MAXY = 0.0; +var MODEL_MINY = 0.0; +var MODEL_WIDTH = 0.0; +var MODEL_HEIGHT = 0.0; +var SVG_WIDTH = 500; +var SVG_HEIGHT = 500; +var SVG_MARGINX = 50; +var SVG_MARGINY = 50; +var VIEW_WIDTH = "19em"; +var VIEW_HEIGHT = "19em"; +var VIEW_MIRROR = 0; + +var GAME_NAME = ""; // name of current game, e.g. "Breakthrough" +var ELEMS = []; // used to store the list of elements +var ELEM_POS = {}; // positions of elements +var RELS = []; // relations +var SUGGESTED_ELEM_SIZEX = 25; // suggested size of elements +var SUGGESTED_ELEM_SIZEY = 25; // suggested size of elements + +var CACHED_MOVES = "" + +var DIM_STR = "" +var ELEM_STR = "" +var RELS_STR = "" +var MOVES_STR = "" + + +// Helper function: sign of a number. +function sign (x) { + if (x > 0.01) { return (1); } + else if (x < -0.01) { return (-1); } + else { return (0); } +} + +// Clears cached moves. +function clear_move_cache () { + CACHED_MOVES = ""; +} + +function set_info (info) { + var res_arr = []; + res_arr = info.split("$"); + if (res_arr.length != 4) { return (false); } + DIM_STR = res_arr[0]; + ELEM_STR = res_arr[1]; + RELS_STR = res_arr[2]; + MOVES_STR = res_arr[3]; + var dim = strip('(', ')', DIM_STR).split(','); + MODEL_MAXX = parseFloat(strip(' ', ' ', dim[0])); + MODEL_MINX = parseFloat(strip(' ', ' ', dim[1])); + MODEL_MAXY = parseFloat(strip(' ', ' ', dim[2])); + MODEL_MINY = parseFloat(strip(' ', ' ', dim[3])); + MODEL_WIDTH = Math.max (SVG_WIDTH / 100, (MODEL_MAXX - MODEL_MINX)); + MODEL_HEIGHT = Math.max (SVG_HEIGHT / 100, (MODEL_MAXY - MODEL_MINY)); + + return (true); +} + +// Send [msg] to server and return response text. +function sync_server_msg (msg) { + var xml_request = new XMLHttpRequest (); + xml_request.open ('POST', 'TossHandler.py', false); + xml_request.setRequestHeader ('Content-Type', + 'application/x-www-form-urlencoded; charset=UTF-8'); + xml_request.send (msg); + resp = xml_request.responseText; + if (resp.indexOf ("MOD_PYTHON ERROR") > -1) { + alert (resp.substring(resp.indexOf("Traceback"))); + return (""); + } + return (resp) +} + +// Send [msg] to server attaching prefix '[cmd]#' and return response text. +function srv (cmd, msg) { + return (sync_server_msg (cmd + '#' + msg)); +} + +// Strip [c1] and [c2] from beginning and end of [str]. +function strip (c1, c2, str) { + if (str.length == 0) return (str); + var i = 0; var j = 0; + for (i = 0; i < str.length; i++) { + if (str.charAt(i) != c1 && str.charAt(i) != c2) break; + } + for (j = str.length - 1; j > -1; j--) { + if (str.charAt(j) != c1 && str.charAt(j) != c2) break; + } + if (i > j) { return ("") }; + return (str.substring(i, j+1)); +} + +// Convert a string [str] representing python list to array and return it. +// WARNING: we use [sep] as separator, it must not occur in list elements! +function convert_python_list (sep, str) { + var res_arr = []; + res_arr = strip('[', ']', str).split(sep); + if (res_arr.length == 1 && res_arr[0] == "") { return ([]); } + for (i = 0; i < res_arr.length; i++) { + res_arr[i] = strip (' ', '\'', res_arr[i]) + } + return (res_arr); +} + + +// Get moves applicable to [elem] in a game. +function get_moves (elem) { + if (CACHED_MOVES == "") { + CACHED_MOVES = MOVES_STR + } + var all_moves = convert_python_list (';', CACHED_MOVES); + var elem_moves = [] + for (i = 0; i < all_moves.length; i++) { + if (all_moves[i].indexOf(elem) >= 0) { + elem_moves.push(all_moves[i]) + } + } + return (elem_moves) +} + +// Get relation tuples. +function get_rels () { + var r = convert_python_list(';', RELS_STR); + var rels = []; + for (var i = 0; i < r.length; i++) { + var rel_name = strip(' ', '\'', r[i].substring(1,r[i].indexOf(','))); + var args_s = r[i].substring(r[i].indexOf('[')+1, r[i].indexOf(']')); + if (rel_name[0] != "_" && args_s != "''") { + rels.push ([rel_name, convert_python_list (',', args_s)]); + } + } + return (rels) +} + +// Translate position from Toss Model coordinates to SVG coordinates. +function translate_pos (pos) { + var x = ((pos[0] - MODEL_MINX) * SVG_WIDTH) / MODEL_WIDTH; + if (VIEW_MIRROR == 0) { + var y = ((pos[1] - MODEL_MINY) * SVG_HEIGHT) / MODEL_HEIGHT; + } else { + var y = ((MODEL_HEIGHT - (pos[1] - MODEL_MINY)) * SVG_WIDTH) / MODEL_HEIGHT; + } + return ([x + SVG_MARGINX, y + SVG_MARGINY]) +} + +// Get elements and positions. +function get_elems_with_pos () { + var l = convert_python_list(',', ELEM_STR); + ELEMS = []; + ELEM_POS = {}; + for (var i = 0; i < l.length; i++) { + var e = convert_python_list (';', l[i]); + ELEMS.push (e[0]); + ELEM_POS[e[0]] = translate_pos ([parseFloat(e[1]), parseFloat(e[2])]); + } +} + + +// Open [file_name] on Toss Server and get info. +function toss_open_db (file_name_params) { + var info = srv ("OPEN_DB", file_name_params); + set_info (info); +} + + +// ---- Two functions below are very basic and thus in this file. --- + +// Create basic svg box. +function create_svg_box (bwidth, bheight, margx, margy, parent_id) { + VIEW_WIDTH = bwidth; + VIEW_HEIGHT = bheight; + SVG_MARGINX = margx; + SVG_MARGINY = margx; + var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.setAttribute('id', 'svg'); + svg.setAttribute('width', bwidth); + svg.setAttribute('height', bheight); + var wx = SVG_WIDTH + 2*SVG_MARGINX; + var wy = SVG_HEIGHT + 2*SVG_MARGINY; + svg.setAttribute('viewBox', '0 0 ' + wx + " " + wy); + document.getElementById(parent_id).appendChild(svg); +} + +// Create new svg element [elem], child of svg, with [attributes]. +function svg_from_string (x, y, sizex, sizey, s) { + var parser = new DOMParser (); + var svgs = '<svg version="1.1" xmlns="http://www.w3.org/2000/svg">'; + var scfx = (SUGGESTED_ELEM_SIZEX - 10) / sizex; + var scfy = (SUGGESTED_ELEM_SIZEY - 10) / sizey; + var sc = "scale(" + scfx + "," + scfy + ")"; + var gs = '<g transform="translate(' + x + "," + y + ") " + sc + '">'; + var doc = parser.parseFromString(svgs+ gs+ s + ' </g> </svg>', "text/xml"); + var elem = document.adoptNode(doc.childNodes[0]); + return(elem.childNodes[0]); +} + + +// Create new svg element [elem], child of svg, with [attributes]. +function add_svg (elem, attributes) { + var elem = document.createElementNS("http://www.w3.org/2000/svg", elem); + elem.setAttribute ("class", "svgelem"); + for (var i = 0; i < attributes.length; i++) { + elem.setAttribute (attributes[i][0], attributes[i][1].toString()); + } + document.getElementById("svg").appendChild(elem); +} Copied: trunk/Toss/WebClient/DefaultStyle.js (from rev 1253, trunk/Toss/WebClient/TossDefaultStyle.js) =================================================================== --- trunk/Toss/WebClient/DefaultStyle.js (rev 0) +++ trunk/Toss/WebClient/DefaultStyle.js 2010-12-18 17:49:52 UTC (rev 1254) @@ -0,0 +1,272 @@ +// JavaScript Toss Module -- DefaultStyle (requires TossConnect.js) + +// This module implements default drawing style for games. +// Functions expected from this module: +// - draw_outline () +// - draw_elem (elem) +// - highlight_elem (elem) +// - unhighlight_elem (elem) +// - draw_rel (rel_name, args) + + +var DEFpawn = '<g transform="translate(-22.5,-22.5)"> \ + <path \ + d="M 22,9 C 19.792,9 18,10.792 18,13 C 18,13.885 18.294,14.712 18.781,15.375 C 16.829,16.497 15.5,18.588 15.5,21 C 15.5,23.034 16.442,24.839 17.906,26.031 C 14.907,27.089 10.5,31.578 10.5,39.5 L 33.5,39.5 C 33.5,31.578 29.093,27.089 26.094,26.031 C 27.558,24.839 28.5,23.034 28.5,21 C 28.5,18.588 27.171,16.497 25.219,15.375 C 25.706,14.712 26,13.885 26,13 C 26,10.792 24.208,9 22,9 z " \ + class="chess-path-A" /> \ + </g>'; + +var DEFknight = '<g transform="translate(-22.5,-22.5)"> \ + <path \ + d="M 22,10 C 32.5,11 38.5,18 38,39 L 15,39 C 15,30 25,32.5 23,18" \ + class="chess-path-B" /> \ + <path \ + d="M 24,18 C 24.384,20.911 18.447,25.369 16,27 C 13,29 13.181,31.343 11,31 C 9.9583,30.056 12.413,27.962 11,28 C 10,28 11.187,29.232 10,30 C 9,30 5.9968,31 6,26 C 6,24 12,14 12,14 C 12,14 13.886,12.098 14,10.5 C 13.274,9.5056 13.5,8.5 13.5,7.5 C 14.5,6.5 16.5,10 16.5,10 L 18.5,10 C 18.5,10 19.282,8.0081 21,7 C 22,7 22,10 22,10" \ + class="chess-path-B" /> \ + <path \ + d="M 9 23.5 A 0.5 0.5 0 1 1 8,23.5 A 0.5 0.5 0 1 1 9 23.5 z" \ + transform="translate(0.5,2)" \ + class="chess-path-C" /> \ + <path \ + d="M 15 15.5 A 0.5 1.5 0 1 1 14,15.5 A 0.5 1.5 0 1 1 15 15.5 z" \ + transform="matrix(0.866,0.5,-0.5,0.866,9.6926,-5.1734)" \ + class="chess-path-C" /> \ + <path \ + d="M 37,39 C 38,19 31.5,11.5 25,10.5" \ + class="chess-path-D" /> \ + </g>'; + +var DEFbishop = '<g transform="translate(-22.5,-22.5)"> \ + <path \ + d="M 9,36 C 12.385,35.028 19.115,36.431 22.5,34 C 25.885,36.431 32.615,35.028 36,36 C 36,36 37.646,36.542 39,38 C 38.323,38.972 37.354,38.986 36,38.5 C 32.615,37.528 25.885,38.958 22.5,37.5 C 19.115,38.958 12.385,37.528 9,38.5 C 7.6459,38.986 6.6771,38.972 6,38 C 7.3541,36.055 9,36 9,36 z " \ + style="stroke-linecap:butt;" class="chess-path-Bx" /> \ + <path \ + d="M 15,32 C 17.5,34.5 27.5,34.5 30,32 C 30.5,30.5 30,30 30,30 C 30,27.5 27.5,26 27.5,26 C 33,24.5 33.5,14.5 22.5,10.5 C 11.5,14.5 12,24.5 17.5,26 C 17.5,26 15,27.5 15,30 C 15,30 14.5,30.5 15,32 z " \ + style="stroke-linecap:butt;" class="chess-path-B" /> \ + <path \ + d="M 25 10 A 2.5 2.5 0 1 1 20,10 A 2.5 2.5 0 1 1 25 10 z" \ + transform="translate(0,-2)" \ + style="stroke-linecap:butt;" class="chess-path-Bx" /> \ + <path \ + d="M 17.5,26 L 27.5,26" \ + style="stroke-linecap:butt;" class="chess-path-D" /> \ + <path \ + d="M 15,30 L 30,30" \ + style="stroke-linecap:butt;" class="chess-path-D" /> \ + <path \ + d="M 22.5,15.5 L 22.5,20.5" \ + style="stroke-linecap:butt;" class="chess-path-D" /> \ + <path \ + d="M 20,18 L 25,18" \ + style="stroke-linecap:butt;" class="chess-path-D" /> \ + </g>'; + +var DEFrook = '<g transform="translate(-22.5,-22.5)"> \ + <path \ + d="M 9,39 L 36,39 L 36,36 L 9,36 L 9,39 z " \ + style="stroke-linecap:butt;" class="chess-path-Bx" /> \ + <path \ + d="M 12,36 L 12,32 L 33,32 L 33,36 L 12,36 z " \ + style="stroke-linecap:butt;" class="chess-path-Bx" /> \ + <path \ + d="M 11,14 L 11,9 L 15,9 L 15,11 L 20,11 L 20,9 L 25,9 L 25,11 L 30,11 L 30,9 L 34,9 L 34,14" \ + style="stroke-linecap:butt;" class="chess-path-B" /> \ + <path \ + d="M 34,14 L 31,17 L 14,17 L 11,14" \ + style="stroke-linecap:butt;" class="chess-path-B" /> \ + <path \ + d="M 31,17 L 31,29.5 L 14,29.5 L 14,17" \ + style="stroke-linecap:butt;" class="chess-path-B" /> \ + <path \ + d="M 31,29.5 L 32.5,32 L 12.5,32 L 14,29.5" \ + class="chess-path-Bx" /> \ + <path \ + d="M 11,14 L 34,14" \ + class="chess-path-D" /> \ + </g>'; + +var DEFqueen = '<g transform="translate(-22.5,-22.5)"> \ + <path \ + d="M 9 13 A 2 2 0 1 1 5,13 A 2 2 0 1 1 9 13 z" \ + transform="translate(-1,-1)" \ + style="fill-rule: none;" class="chess-path-B" /> \ + <path \ + d="M 9 13 A 2 2 0 1 1 5,13 A 2 2 0 1 1 9 13 z" \ + transform="translate(15.5,-5.5)" \ + style="fill-rule: none;" class="chess-path-B" /> \ + <path \ + d="M 9 13 A 2 2 0 1 1 5,13 A 2 2 0 1 1 9 13 z" \ + transform="translate(32,-1)" \ + style="fill-rule: none;" class="chess-path-B" /> \ + <path \ + d="M 9 13 A 2 2 0 1 1 5,13 A 2 2 0 1 1 9 13 z" \ + transform="translate(7,-4.5)" \ + style="fill-rule: none;" class="chess-path-B" /> \ + <path \ + d="M 9 13 A 2 2 0 1 1 5,13 A 2 2 0 1 1 9 13 z" \ + transform="translate(24,-4)" \ + style="fill-rule: none;" class="chess-path-B" /> \ + <path \ + d="M 9,26 C 17.5,24.5 30,24.5 36,26 L 38,14 L 31,25 L 31,11 L 25.5,24.5 L 22.5,9.5 L 19.5,24.5 L 14,10.5 L 14,25 L 7,14 L 9,26 z " \ + style="stroke-linecap:butt;" class="chess-path-B" /> \ + <path \ + d="M 9,26 C 9,28 10.5,28 11.5,30 C 12.5,31.5 12.5,31 12,33.5 C 10.5,34.5 10.5,36 10.5,36 C 9,37.5 11,38.5 11,38.5 C 17.5,39.5 27.5,39.5 34,38.5 C 34,38.5 35.5,37.5 34,36 C 34,36 34.5,34.5 33,33.5 C 32.5,31 32.5,31.5 33.5,30 C 34.5,28 36,28 36,26 C 27.5,24.5 17.5,24.5 9,26 z " \ + style="stroke-linecap:butt;" class="chess-path-B" /> \ + <path \ + d="M 11.5,30 C 15,29 30,29 33.5,30" \ + class="chess-path-D" /> \ + <path \ + d="M 12,33.5 C 18,32.5 27,32.5 33,33.5" \ + class="chess-path-D" /> \ + <path \ + d="M 10.5,36 C 15.5,35 29,35 34,36" \ + class="chess-path-D" /> \ + </g>'; + +var DEFking = '<g transform="translate(-22.5,-22.5)"> \ + <path d="M 22.5,11.625 L 22.5,6" class="chess-path-D" /> \ + <path d="M 22.5,25 C 22.5,25 27,17.5 25.5,14.5 C 25.5,14.5 24.5,12 22.5,12 C 20.5,12 19.5,14.5 19.5,14.5 C 18,17.5 22.5,25 22.5,25" \ + style="fill:stroke-linecap:butt;" class="chess-path-B" /> \ + <path d="M 11.5,37 C 17,40.5 27,40.5 32.5,37 L 32.5,30 C 32.5,30 41.5,25.5 38.5,19.5 C 34.5,13 25,16 22.5,23.5 L 22.5,27 L 22.5,23.5 C 19,16 9.5,13 6.5,19.5 C 3.5,25.5 11.5,29.5 11.5,29.5 L 11.5,37 z " \ + class="chess-path-D" /> \ + <path d="M 20,8 L 25,8" class="chess-path-D" /> \ + <path d="M 11.5,29.5 C 17,27 27,27 32.5,30" class="chess-path-D" /> \ + <path d="M 11.5,37 C 17,34.5 27,34.5 32.5,37" \ + class="chess-path-D" /> \ + <path d="M 11.5,33.5 C 17,31.5 27,31.5 32.5,33.5" \ + class="chess-path-D" /> \ + </g>'; + +// Draw a box around the board. +function draw_outline () { + var w = SVG_WIDTH + 2*SVG_MARGINX; + var h = SVG_HEIGHT + 2*SVG_MARGINY; + add_svg ("rect", [["class", "board-outline"], ["width", w], ["height", h]]); +} + +// Draw the element [elem]. +function draw_elem (elem) { + var pos = ELEM_POS[elem]; + add_svg ("rect", + [["x", pos[0] - SUGGESTED_ELEM_SIZEX], + ["y", pos[1] - SUGGESTED_ELEM_SIZEY], + ["width", 2 * SUGGESTED_ELEM_SIZEX], + ["height", 2 * SUGGESTED_ELEM_SIZEX], + ["id", "elem_" + elem], + ["class", "model-elem"], + ["onclick", ("handle_elem_click('" + elem + "')")]] + ); +} + +// Highlight the element [elem]. +function highlight_elem (elem) { + var e = document.getElementById ("elem_" + elem); + e.setAttribute ("class", "model-elem-highlight"); +} + +// Unhighlight the element [elem]. +function unhighlight_elem (elem) { + var e = document.getElementById ("elem_" + elem); + e.setAttribute ("class", "model-elem"); +} + +// Draw relation [rel_name] between elements [args]. +function draw_rel (rel_name, args) { + if (args.length == 1) { + var is = 'id="' + "pred_" + args[0] + "_" + rel_name + '" '; + var hs = 'onclick="' + "handle_elem_click('" + args[0] + "')" + '" '; + var pos = ELEM_POS[args[0]]; + if (rel_name == "P") { // Tic-tac-toe cross + var cs = 'class="' + "model-pred-" + rel_name + '" '; + var ls1 = '<line x1="-10" y1="-10" x2="10" y2="10" />'; + var ls2 = '<line x1="10" y1="-10" x2="-10" y2="10" />'; + var cr = svg_from_string (pos[0], pos[1], 12, 12, + '<g ' + cs + is + hs + '>' + ls1 + ls2 + '</g>'); + document.getElementById("svg").appendChild(cr); + } else if (rel_name == "R") { // Robber in Entanglement + add_svg ("circle", + [["cx", pos[0]], ["cy", pos[1]], ["r", SUGGESTED_ELEM_SIZEX - 5], + ["id", "pred_" + args[0] + "_" + rel_name], + ["class", "model-pred-" + rel_name], + ["onclick", ("handle_elem_click('" + args[0] + "')")]]); + } else if (rel_name == "wP") { // Chess Figure: white pawn + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessW" ' + is + hs + '>' + DEFpawn + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "bP") { // Chess Figure: black pawn + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessB" ' + is + hs + '>' + DEFpawn + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "wN") { // Chess Figure: white knight + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessW" ' + is + hs + '>' + DEFknight + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "bN") { // Chess Figure: black knight + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessB" ' + is + hs + '>' + DEFknight + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "wB") { // Chess Figure: white bishop + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessW" ' + is + hs + '>' + DEFbishop + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "bB") { // Chess Figure: black bishop + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessB" ' + is + hs + '>' + DEFbishop + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "wR") { // Chess Figure: white rook + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessW" ' + is + hs + '>' + DEFrook + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "bR") { // Chess Figure: black rook + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessB" ' + is + hs + '>' + DEFrook + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "wQ") { // Chess Figure: white queen + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessW" ' + is + hs + '>' + DEFqueen + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "bQ") { // Chess Figure: black queen + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessB" ' + is + hs + '>' + DEFqueen + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "wK") { // Chess Figure: white king + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessW" ' + is + hs + '>' + DEFking + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "bK") { // Chess Figure: black king + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessB" ' + is + hs + '>' + DEFking + '</g>'); + document.getElementById("svg").appendChild(f); + } else { + add_svg ("circle", + [["cx", pos[0]], ["cy", pos[1]], ["r", SUGGESTED_ELEM_SIZEX - 12], + ["id", "pred_" + args[0] + "_" + rel_name], + ["class", "model-pred-" + rel_name], + ["stroke-width", (SUGGESTED_ELEM_SIZEX / 10) + 2], + ["onclick", ("handle_elem_click('" + args[0] + "')")]]); + } + } + if (args.length == 2) { + if (rel_name == "E") { + var pos1 = ELEM_POS[args[0]]; + var pos2 = ELEM_POS[args[1]]; + if (sign (pos1[0] - pos2[0]) == 0) { + var d = SUGGESTED_ELEM_SIZEY * sign (pos1[1] - pos2[1]); + add_svg ("line", [["x1", pos1[0]], ["y1", pos1[1] - d], + ["x2", pos2[0]], ["y2", pos2[1] + d], + ["class", "model-edge-E"]]); + } else if (sign (pos1[1] - pos2[1]) == 0) { + var d = SUGGESTED_ELEM_SIZEX * sign (pos1[0] - pos2[0]); + add_svg ("line", [["x1", pos1[0] - d], ["y1", pos1[1]], + ["x2", pos2[0] + d], ["y2", pos2[1]], + ["class", "model-edge-E"]]); + } + else { + var dx = SUGGESTED_ELEM_SIZEX * sign (pos1[0] - pos2[0]); + var dy = SUGGESTED_ELEM_SIZEY * sign (pos1[1] - pos2[1]); + add_svg ("line", [["x1", pos1[0] + dx], ["y1", pos1[1] + dy], + ["x2", pos2[0] - dx], ["y2", pos2[1] - dy], + ["class", "model-edge-E"]]); + } + } + } +} Copied: trunk/Toss/WebClient/Handler.py (from rev 1253, trunk/Toss/WebClient/TossHandler.py) =================================================================== --- trunk/Toss/WebClient/Handler.py (rev 0) +++ trunk/Toss/WebClient/Handler.py 2010-12-18 17:49:52 UTC (rev 1254) @@ -0,0 +1,227 @@ +import subprocess +import socket +import time +from Wrapper import * +from mod_python import apache, Cookie +from pysqlite2 import dbapi2 as sqlite3 + +DB_FILE = "/var/www/WebClient/tossdb.sqlite" + +TUID = "toss_id_05174_" + +def tmp_log (str): + file = open ("/tmp/th.log", 'a') + file.write (str) + file.close() + +def get_all_from_db (db, tbl, select_s): + res = [] + for r in db.execute("select * from " + tbl + " where " + select_s): + res.append(r) + return (res) + +def open_toss_server (port): + args = ["/var/www/WebClient/TossServer", + "-s", "localhost", "-p", str(port)] + server_proc = subprocess.Popen(args) + time.sleep (0.1) + return (port) + +def get_global_lock (db): + cur = db.cursor () + cur.execute ("update lock set locked='true' " + + " where locked='false' and tid='" + str(TUID) + "'") + db.commit () + if cur.rowcount == 1: + return + time.sleep (0.1) + get_global_lock (db) + +def release_global_lock (db): + db.execute ("update lock set locked='false' " + + " where locked='true' and tid='" + str(TUID) + "'") + db.commit () + +def get_toss_port (db): + get_global_lock (db) + free_ports = get_all_from_db (db, "ports", "locked='false'") + if len(free_ports) == 0: + fid = 0 + for f in db.execute ("select count(*) from ports"): + fid = int(f[0]) + port = 8110+fid+1 + db.execute ("insert into ports(port, locked) values (?, ?)", + (port, 'true')) + release_global_lock (db) + open_toss_server (port) + return (port) + (port, _) = free_ports[0] + db.execute ("update ports set locked='true' where port=" + str(port)) + release_global_lock (db) + return (port) + +def release_toss_port (db, port): + db.execute ("update ports set locked='false' where port=" + str(port)) + db.commit () + +def cp (f1, f2): + subprocess.call(["cp", f1, f2]) + +def list_plays (db, game, player_id): + or_s = "(player1='" + player_id + "' or player2='" + player_id + "')" + plays = get_all_from_db (db, "cur_states", "game='"+ game + "' and " + or_s) + def play_name (p): + (pid, g, p1, p2, move, _, _, _) = p + return ("/plays/" + str(g) + "_" + str(p1) + "_" + str(p2) + "_" + + str(pid) + "_" + str(move)) + return (str([play_name (p) for p in plays])) + +def db_cur_insert (db, game, p1, p2, pid, move, toss, info, svg_str): + db.execute ("insert into cur_states(playid, game, player1, player2, move, toss, info, svg) values (?, ?, ?, ?, ?, ?, ?, ?)", + (pid, game, p1, p2, move, toss, info, svg_str)) + db.commit () + +def db_old_insert (db, game, p1, p2, pid, move, toss, info, svg_str): + db.execute ("insert into old_states(playid, game, player1, player2, move, toss, info, svg) values (?, ?, ?, ?, ?, ?, ?, ?)", + (pid, game, p1, p2, move, toss, info, svg_str)) + db.commit () + +def get_game_info (client): + dim_s = str(client.model.get_dim()) + model_s = str(client.model.get_elems_with_pos()) + rels_s = str(client.model.get_rels_simple()) + moves_s = str(client.cur_moves()) + return (dim_s + "$" + model_s + "$" + rels_s + "$" + moves_s) + +def new_play (db, client, game, p1, p2, pid, move): + res = get_all_from_db (db, "games", "game='" + game + "'") + (_, toss) = res[0] + client.open_from_str (toss) + info = get_game_info (client) + model = client.get_model () + db_cur_insert (db, game, p1, p2, pid, move, model, info, "") + return (info) + +def game_select_s (g, p1, p2, pid, m): + return("game='" + g + "' and player1='" + p1 + "' and player2='" + p2 + + "' and playid=" + pid + " and move=" + m) + +def open_db (db, game, p1, p2, pid, move): + select_s = game_select_s (game, p1, p2, pid, move) + res = get_all_from_db (db, "cur_states", select_s) + (_, _, _, _, _, _, info, _) = res[0] + return (info) + + +def move_play (db, client, move_tup, g, p1, p2, pid, m): + select_s = game_select_s (g, p1, p2, pid, m) + old_res = get_all_from_db (db, "cur_states", select_s) + (_, _, _, _, _, old_toss, old_info, old_svg) = old_res[0] + res = get_all_from_db (db, "games", "game='" + g + "'") + (_, game_toss) = res[0] + client.open_from_str (game_toss + "\n MODEL " + old_toss) + (move1, move2, move3) = move_tup + client.make_move (move1, move2, move3) + new_toss = client.get_model () + new_info = get_game_info (client) + db.execute ("delete from cur_states where " + select_s) + db_old_insert (db, g, p1, p2, pid, m, old_toss, old_info, old_svg) + db_cur_insert (db, g, p1, p2, pid, int(m) + 1, new_toss, new_info, "") + return (new_info) + +def upd_svg (db, g, p1, p2, pid, m, svg_s): + select_s = game_select_s (g, p1, p2, pid, m) + db.execute ("update cur_states set svg='" + svg_s + "' where " + select_s) + db.commit () + +def passwd_from_db (db, uid): + res = get_all_from_db (db, "users", "id='" + uid + "'") + if len(res) > 1: raise Exception ("db", "multiple entries for " + uid) + if len(res) == 0: return (None) + (uid, _, _, _, passwd) = res[0] + return (str(passwd)) + +def confirm_username (db, req): + cookies = Cookie.get_cookies(req) + if not (cookies.has_key(TUID + 'username')): return "" + if not (cookies.has_key(TUID + 'passphrase')): return "" + uid = cookies[TUID + 'username'].value + pwd1 = cookies[TUID + 'passphrase'].value + pwd2 = passwd_from_db (db, uid) + if (pwd1 != pwd2): return "" + return (uid) + +def login_user (db, req, uid, pwd): + db_pwd = passwd_from_db (db, uid) + if not db_pwd: return ("no such user registered") + if (pwd != db_pwd): return ("wrong password") + t = time.time() + 3600; + cookie1 = Cookie.Cookie(TUID + 'username', uid, expires=t) + cookie2 = Cookie.Cookie(TUID + 'passphrase', pwd, expires=t) + Cookie.add_cookie(req, cookie1) + Cookie.add_cookie(req, cookie2) + return ("OK") + +def register_user (db, ui): + if len(ui) != 5: return (False) + (uid, name, surname, email, pwd) = (ui[0], ui[1], ui[2], ui[3], ui[4]) + if passwd_from_db (db, uid): return (False) + db.execute ("insert into users(id, name, surname, email, passwd) " + + "values (?, ?, ?, ?, ?)", (uid, name, surname, email, pwd)) + db.commit () + return (True) + +def get_free_id (db): + fid = 0 + for f in db.execute ("select count(*) from cur_states"): + fid = int(f[0]) + return (fid + 1) + +def handler(req): + req.content_type = "text/plain" + db = sqlite3.connect(DB_FILE) + usr = confirm_username (db, req) + msg = req.read () + #tmp_log(msg) + cmd, sep, data = msg.partition('#') + if cmd == "USERNAME": + req.write(usr) + return apache.OK + if cmd == "REGISTER": + ui = data.split('$') + if register_user (db, ui): + req.write("Registration successful for " + ui[0] + ".") + return apache.OK + req.write("Registration failed:\n username "+ui[0]+" already in use."+ + "\nPlease choose another username and try again.") + return apache.OK + if cmd == "LOGIN": + uname, sep, pwd = data.partition(' ') + res = login_user (db, req, uname, pwd) + if res == "OK": + req.write("OK") + return apache.OK + req.write("Login failed for " + uname + ": " + res) + return apache.OK + if cmd == "LOGOUT": + cookie = Cookie.Cookie(TUID + 'passphrase', "a") + cookie = Cookie.Cookie(TUID + 'username', "a") + Cookie.add_cookie(req, cookie) + req.write ("user logged out: " + usr + ".") + return apache.OK + if cmd == "FREEID": + req.write(str(get_free_id (db))) + return apache.OK + if (cmd == "LIST_PLAYS") or (cmd == "OPEN_DB") or (cmd == "UPD_SVG"): + res = eval (cmd.lower() + "(db, " + data + ")") + req.write(str(res)) + return apache.OK + if (cmd == "NEW_PLAY") or (cmd == "MOVE_PLAY"): + port = get_toss_port (db) + c = SystemClient ("localhost", port) + res = eval (cmd.lower() + "(db, " + data + ")") + release_toss_port (db, port) + req.write(str(res)) + return apache.OK + req.write("MOD_PYTHON ERROR ; Traceback: Unknown Toss Command! \n " + cmd) + return apache.OK Added: trunk/Toss/WebClient/Login.js =================================================================== --- trunk/Toss/WebClient/Login.js (rev 0) +++ trunk/Toss/WebClient/Login.js 2010-12-18 17:49:52 UTC (rev 1254) @@ -0,0 +1,113 @@ +// JavaScript Toss Module -- Login (requires Main.js, all other) + +TSALT = "toss##in$$some167S4lT_-"; +CORRMSG = "\nPlease correct this and try again." + + +// Simple encryption +function crypt (s) { + var c = Crypto.SHA256(s, true); + var d = c.replace("#", "@"); + return (d.replace("$", "@")); +} + +// Setup a user +function setup_user (un) { + UNAME = un + document.getElementById("topuser").innerHTML = "Welcome " + un; + document.getElementById("loginform").style.display = "none"; + document.getElementById("topright-register").style.display = "none"; + document.getElementById("topright").style.display = "inline"; + document.getElementById("welcome").style.display = "none"; + document.getElementById("plays").style.display = "block"; + list_plays ("Breakthrough"); + list_plays ("Chess"); + list_plays ("Entanglement"); + list_plays ("Gomoku"); + list_plays ("Tic-Tac-Toe"); +} + +// Clear view +function clear_view () { + document.getElementById("loginform").style.display = "inline"; + document.getElementById("topright-register").style.display = "inline"; + document.getElementById("topright").style.display = "none"; + document.getElementById("topuser").innerHTML = ""; + document.getElementById("plays").style.display = "none"; + document.getElementById("game-title").style.display = "none"; + document.getElementById("game-disp").style.display = "none"; + document.getElementById("welcome").style.display = "block"; +} + +// Onload handler +function startup () { + if (navigator.userAgent.indexOf('MSIE') !=-1) { + document.getElementById("nosvg").style.display = "block"; + } else { + var un = srv("USERNAME", "user"); + if (un != "") { setup_user (un) }; + } +} + +// Login +function login () { + un = document.getElementById('username').value; + pwd = document.getElementById('password').value; + resp = sync_server_msg ("LOGIN#" + un + " " + crypt(TSALT + pwd)); + if (resp == "OK") { + setup_user (un) + } else { + alert (resp) + } +} + +// Logout +function logout () { + clear_view (); +} + +// Register new user +function register () { + un = document.getElementById('username').value; + pwd = document.getElementById('password').value; + rptpwd = document.getElementById('rptpassword').value; + name = document.getElementById('name').value; + surname = document.getElementById('surname').value; + email = document.getElementById('email').value; + if (un.length < 2) { + alert ("Your username must contain at least 2 letters." + CORRMSG); + return; + } + if (un.indexOf(" ") > 0) { + alert ("Your username must not contain spaces." + CORRMSG); + return; + } + if (pwd.length < 3) { + alert ("Your password is too short." + CORRMSG); + return; + } + if (pwd != rptpwd) { + alert ("Password and Repeated Password do not match." + CORRMSG); + return; + } + if (name == "") { + alert ("Your name was not given and it is necessary." + CORRMSG); + return; + } + if (surname == "") { + alert ("Your surname was not given and it is necessary." + CORRMSG); + return; + } + if (email.indexOf("@") < 1 || email.indexOf(".") < 1) { + alert ("Please provide a valid email address."); + return; + } + if (un.indexOf ("$") > 0 || name.indexOf ("$") > 0 || + surname.indexOf ("$") > 0 || email.indexOf ("$") > 0) { + alert ("Your data must not contain $, i.e. the dolar sign." + CORRMSG); + return; + } + data = un + "$" + name + "$" + surname + "$" + email; + resp = sync_server_msg ("REGISTER#" + data + "$" + crypt(TSALT + pwd)); + alert (resp); +} Copied: trunk/Toss/WebClient/Main.js (from rev 1253, trunk/Toss/WebClient/TossMain.js) =================================================================== --- trunk/Toss/WebClient/Main.js (rev 0) +++ trunk/Toss/WebClient/Main.js 2010-12-18 17:49:52 UTC (rev 1254) @@ -0,0 +1,321 @@ +// JavaScript Toss Module -- Main (requires Connect.js, DefaultStyle.js) + +var ELEM_COUNTERS = {}; +var CUR_MOVE = ""; +var CUR_ELEMS = []; + +var PLAYS = []; +var CUR_PLAY_I = -1; + +var FRIENDS = [] + +var MAX_OPNT_LEN = 20; +var FULL_OPNT_LEN = 0; +var CUR_OPNT_START = 0; + +// Get model information from server. +function get_model_info () { + get_elems_with_pos (); + for (var i = 0; i < ELEMS.length; i++) { + ELEM_COUNTERS[ELEMS[i]] = 0; + } + RELS = get_rels (); + var sqrt = Math.round (Math.sqrt (ELEMS.length)); + if (sqrt * sqrt == ELEMS.length) { // perhaps a grid + SUGGESTED_ELEM_SIZEX = SVG_WIDTH / (2.0 * (sqrt-1)); + SUGGESTED_ELEM_SIZEY = SVG_HEIGHT / (2.0 * (sqrt-1)); + } else { + SUGGESTED_ELEM_SIZEX = SVG_WIDTH / 20; + SUGGESTED_ELEM_SIZEY = SVG_HEIGHT / 20; + } +} + +// Draw the model using function from Toss[X]Style.js. +// WARNING: must call get_model_info first! +function draw_model () { + draw_outline (); + for (var i = 0; i < ELEMS.length; i++) { + draw_elem (ELEMS[i]); + } + for (var i = 0; i < RELS.length; i++) { + draw_rel (RELS[i][0], RELS[i][1]); + } +} + +// Clear whole svg box. +function clear_svg () { + clear_move_cache (); + ELEM_COUNTERS = {}; + CUR_MOVE = ""; + CUR_ELEMS = []; + document.getElementById('cur-move').innerHTML = "none"; + var svg_e = document.getElementById("svg"); + svg_e.parentNode.removeChild (svg_e); +} + +// Full redraw. +function full_redraw () { + clear_svg (); + document.getElementById("working").style.display = "block"; + get_model_info (); + create_svg_box (VIEW_WIDTH, VIEW_HEIGHT, SVG_MARGINX, SVG_MARGINY, "board"); + draw_model (); + document.getElementById("working").style.display = "none"; +} + +// Helper function: get value elements from a move string [s]. +function get_move_elems (s) { + var vals = []; + var arr = strip('(', ')', s).split(','); + for (var i = 0; i < arr.length; i++) { + if (arr[i].indexOf(':') > -1) { + var v = arr[i].substring (arr[i].indexOf(':')+1, arr[i].length); + vals.push (strip ('\'', ' ', strip ('{', '}', v))); + } + } + return (vals) +} + +// Helper function: highlight move, unhighlight old, save current. +function show_move (m) { + var m_act = get_move_elems (m); + var m_rule = m.substring (m.indexOf("},")+4, m.lastIndexOf(',')-1); + for (var i = 0; i < CUR_ELEMS.length; i++) { + unhighlight_elem (CUR_ELEMS[i]); + } + for (var i = 0; i < m_act.length; i++) { + highlight_elem (m_act[i]); + } + var m_str = strip (' ', ' ', m_act.toString ()); + if (m_str == "") { + document.getElementById('cur-move').innerHTML = "none"; + } else { + document.getElementById('cur-move').innerHTML = + m_rule + ': <br/>' + m_str; + } + CUR_ELEMS = m_act; + CUR_MOVE = m.toString(); +} + +// Handler for clicks on elements. +function handle_elem_click (elem) { + var moves = get_moves (elem); + if (moves.length > ELEM_COUNTERS[elem]) { + show_move (moves[ELEM_COUNTERS[elem]]); + ELEM_COUNTERS[elem] += 1; + } else if (moves.length > 0) { + show_move (moves[0]); + ELEM_COUNTERS[elem] = 1; + } +} + +function play_py_id (i) { + return ("'" + GAME_NAME + "', '" + PLAYS[i][0] + "', '" + + PLAYS[i][1] + "', '" + PLAYS[i][2] + "', '" + PLAYS[i][3] + "'") +} + +function new_play_item (game, i) { + var li = document.createElement('li'); + li.setAttribute ("class", "plays-list-elem"); + li.setAttribute ("id", "plays-list-" + game + "-elem-" + i); + var p = PLAYS[i][2]; + li.innerHTML = "" + PLAYS[i][2] + ': ' + PLAYS[i][0] + " vs " + + PLAYS[i][1] + " " + //" move " + PLAYS[i][3] + " "+ + '<a title="Open" href="#" onclick="'+ "play_click('"+ game + "', " + p + + ", " + i + ')">Open</a>'; + // +'<a href="#" onclick="'+ "del_play('"+ fn + "')" + '">Delete</a>'; + return (li); +} + +function list_plays (game) { + var lst = srv ("LIST_PLAYS", "'" + game + "', '" + UNAME + "'"); + PLAYS = convert_python_list (',', lst); + var plist = document.getElementById("plays-list-" + game); + while (plist.childNodes.length > 0) { plist.removeChild(plist.firstChild); } + var d = game.length + 2; + for (var i = 0; i < PLAYS.length; i++) { + var p = PLAYS[i].substring(PLAYS[i].lastIndexOf('/') + d); + PLAYS[i] = convert_python_list ('_', p); + plist.appendChild(new_play_item (game, i)); + } + if (PLAYS.length == 0) { + document.getElementById("plays-list-" + game).style.display = "none"; + } else { + document.getElementById("plays-list-" + game).style.display = "block"; + } +} + +function game_click (game) { + document.getElementById("welcome").style.display = "none"; + document.getElementById("game-disp").style.display = "none"; + document.getElementById("plays").style.display = "none"; + GAME_NAME = game; + if (game == "Tic-Tac-Toe") { // bigger margins needed + create_svg_box ("19em", "19em", 130, 130, "board"); + } else { + create_svg_box ("19em", "19em", 40, 40, "board"); + } + document.getElementById("opening").style.display = "block"; + document.getElementById("opening").style.display = "none"; + document.getElementById("game-disp").style.display = "block"; +} + +function play_click (game, play_id, pi) { + list_plays (game); + game_click (game); + document.getElementById ("game-title").innerHTML = game; + document.getElementById("game-disp").style.display = "block"; + document.getElementById("play-number").innerHTML = "" + play_id; + CUR_PLAY_I = pi; + VIEW_MIRROR = (PLAYS[CUR_PLAY_I][0] == UNAME) ? 0 : 1; + document.getElementById("cur-player").innerHTML = + PLAYS[CUR_PLAY_I][PLAYS[CUR_PLAY_I][3] % 2]; + toss_open_db (play_py_id(pi)); + full_redraw (); +} + + +// Apply current move. +function make_move () { + if (CUR_MOVE == "") return; + var m = PLAYS[CUR_PLAY_I][3] % 2; + if (PLAYS[CUR_PLAY_I][m] != UNAME) { + alert ("It is your Opponent's turn"); + return; + } + var info = srv("MOVE_PLAY", 'c, '+ CUR_MOVE +', '+ play_py_id (CUR_PLAY_I)); + set_info (info); + clear_move_cache (); + CUR_MOVE = ""; + CUR_ELEMS = []; + ELEM_COUNTERS = {}; + document.getElementById("cur-player").innerHTML = + PLAYS[CUR_PLAY_I][(m + 1) % 2]; + document.getElementById('cur-move').innerHTML = "none"; + full_redraw (); + PLAYS[CUR_PLAY_I][3] = parseInt(PLAYS[CUR_PLAY_I][3]) + 1; + srv ("UPD_SVG", play_py_id(CUR_PLAY_I) + ", " + svg_string()); + var old_li = document.getElementById ("plays-list-" + GAME_NAME + "-elem-" + CUR_PLAY_I); + var li = new_play_item (GAME_NAME, CUR_PLAY_I); + old_li.parentNode.replaceChild (li, old_li); +} + + +function del_play (play) { + alert ("Deleting " + play); +} + +function store_friend_names () { + for (var i = 0; i < FRIENDS.length; i++) { + ID_TO_USER_MAP[FRIENDS[i].id] = FRIENDS[i].name; + ID_TO_USER_FNAME_MAP[FRIENDS[i].id] = FRIENDS[i].first_name; + } +} + +function opponent_item (data, index) { + var li = document.createElement('li'); + li.setAttribute ("class", "opponents-list-elem"); + li.setAttribute ("id", "opponent-" + data.id + "-" + index); + li.innerHTML = '<a href="#" onclick="new_play_do(' + data.id + ')">' + + data.name + '</a>'; + return (li); +} + +function data_cmp (d1, d2) { + if (d1.name < d2.name) { return -1; } + if (d1.name > d2.name) { return 1; } + return (0); +} + +function make_opnt_list () { + var o = document.getElementById("opponents-list"); + FULL_OPNT_LEN = FRIENDS.length + 1; + CUR_OPNT_START = 0; + document.getElementById("opponents-prev").style.display = "none"; + if (MAX_OPNT_LEN > FULL_OPNT_LEN) { + document.getElementById("opponents-next").style.display = "none" + } + var zeroli = document.createElement('li'); + zeroli.setAttribute ("class", "opponents-list-elem"); + zeroli.setAttribute ("id", "opponent-" + "-0"); + zeroli.innerHTML = '<a href="#" onclick="new_play_do(-1)">Play against Yourself</a>'; + o.appendChild (zeroli); + for (var i = 0; i < FRIENDS.length; i++) { + var oi = opponent_item (FRIENDS[i], i+1); + if (i > MAX_OPNT_LEN - 2) { oi.style.display = "none"; } + o.appendChild (oi); + } + document.getElementById("opponents").style.display = "block"; +} + +function new_play (game) { + if (UNAME == "") { alert ("Please log in to create plays"); return; } + GAME_NAME = game; + make_opnt_list (); +} + +function opponents_next () { + for (var i = CUR_OPNT_START; i < CUR_OPNT_START + MAX_OPNT_LEN; i++) { + document.getElementById("opponent-" + "-" + i).style.display = "none"; + } + CUR_OPNT_START += MAX_OPNT_LEN; + for (var i = CUR_OPNT_START; i < CUR_OPNT_START + MAX_OPNT_LEN; i++) { + if (i < FULL_OPNT_LEN) { + document.getElementById("opponent-" + "-" + i).style.display = "list-item"; + } + } + document.getElementById("opponents-prev").style.display = "block" + if (CUR_OPNT_START + MAX_OPNT_LEN > FULL_OPNT_LEN) { + document.getElementById("opponents-next").style.display = "none" + } +} + +function opponents_prev () { + for (var i = CUR_OPNT_START; i < CUR_OPNT_START + MAX_OPNT_LEN; i++) { + if (i < FULL_OPNT_LEN) { + document.getElementById("opponent-" + "-" + i).style.display = "none"; + } + } + CUR_OPNT_START -= MAX_OPNT_LEN; + for (var i = CUR_OPNT_START; i < CUR_OPNT_START + MAX_OPNT_LEN; i++) { + document.getElementById("opponent-" + "-" + i).style.display = "list-item"; + } + document.getElementById("opponents-next").style.display = "block" + if (CUR_OPNT_START == 0) { + document.getElementById("opponents-prev").style.display = "none" + } +} + +function svg_string () { + var svg_el = document.getElementById ("svg"); + var svg_s = (new XMLSerializer()).serializeToString(svg_el); + svg_s = svg_s.replace(/onclick="[^\"]*"/g, ""); + return ("'''" + svg_s + "'''"); +} + +function new_play_do (opp_uid) { + list_plays (GAME_NAME) + game_click (GAME_NAME) + document.getElementById("opponents").style.display = "none"; + var olist = document.getElementById("opponents-list"); + while (olist.childNodes.length > 0) { olist.removeChild(olist.firstChild); } + if (opp_uid == -1) { opp_uid = UNAME; } + if (opp_uid == 0 || UNAME == "") { return; } + document.getElementById("plays-list-" + GAME_NAME).style.display = "block"; + FREE_PLAY_NO = parseInt(srv("FREEID", "play")) + document.getElementById("play-number").innerHTML = "" + FREE_PLAY_NO; + CUR_PLAY_I = PLAYS.length; + VIEW_MIRROR = 0; + document.getElementById("cur-player").innerHTML = UNAME; + document.getElementById("game-disp").style.display = "block"; + document.getElementById("plays").style.left = "30em"; + var p = [UNAME, opp_uid, FREE_PLAY_NO, 0]; + PLAYS.push(p); + var fn = play_py_id (CUR_PLAY_I); + info = srv ("NEW_PLAY", "c, " + fn); + set_info(info); + full_redraw (); + srv ("UPD_SVG", play_py_id(CUR_PLAY_I) + ", " + svg_string()); + li = new_play_item (GAME_NAME, CUR_PLAY_I); + document.getElementById("plays-list-" + GAME_NAME).appendChild(li); +} Modified: trunk/Toss/WebClient/README =================================================================== --- trunk/Toss/WebClient/README 2010-12-18 00:52:28 UTC (rev 1253) +++ trunk/Toss/WebClient/README 2010-12-18 17:49:52 UTC (rev 1254) @@ -7,19 +7,19 @@ in the file /etc/apache2/sites-enabled/[your-site] add e.g. <Directory /var/www/WebClient> AddHandler mod_python .py - PythonHandler TossHandler + PythonHandler Handler # During development you might turn debugging on PythonDebug On </Directory> -The main handler script is called TossHander.py (server side) and corresponding -JavaScript functions are in Toss*.js. To start client open index.html, but +The main handler script is called Hander.py (server side) and corresponding +JavaScript functions are in *.js. To start client open index.html, but first make sure that WebClient is linked in /var/www (ln -s should suffice). -Then run "./make_db" from WebClient and make sure TossHandler top is ok. +Then run "./make_db" from WebClient and make sure Handler entry (above) is ok. Also copy Server from main Toss dir as TossServer to the WebClient directory. TODO: - - better register html and user table + - use name in interface, try buttons, add oponents table and adding page - move interface: first click all, second click toggle, if one - confirm msg - after the above: remove left-of-board div, confirm in the middle - after the above: show game result in the middle / instead of move Copied: trunk/Toss/WebClient/Style.css (from rev 1253, trunk/Toss/WebClient/TossStyle.css) =================================================================== --- trunk/Toss/WebClient/Style.css (rev 0) +++ trunk/Toss/WebClient/Style.css 2010-12-18 17:49:52 UTC (rev 1254) @@ -0,0 +1,515 @@ +/* General */ + +html { + height: 100%; + width: 100%; +} + +body { + background-color: #b5bf8f; + font-family: Verdana, 'TeXGyreHerosRegular', sans; + height: 100%; +} + +.reglabel { + float: left; + clear: left; + width: 10em; +} + +#logo { + font-size: 2em; + float: left; + font-family: arial, 'OFLSortsMillGoudyRegular', serif; + width: 4.5em; + padding-left: 0.25em; +} + +#logo a, #logo a:link, #logo a:active, #logo a:visited { + color: #ffe4aa; + background-color: transparent; + text-decoration: none; +} + +#logo a:hover { + color: #b5bf8f; +} + +.logo-in { + /*font-family: 'OFL Sorts Mill Goudy TT', arial, serif; + font-size: 1.2em;*/ +} + +#top { + font-weight: bold; + position: absolute; + top: 0px; + left: 0px; + width: 100%; + height: 2.5em; + color: #ffe4aa; + background-color: #400827; + border-color: #260314; + border-style: solid; + border-width: 0px 0px 5px 0px; +} + +#topbar { + margin-left: 9.5em; + padding-left: 1em; + padding-right: 1em; + padding-top: 0.7em; +} + +#topright { + float: right; + margin-right: 0em; + display: none; +} + +#topright-register { + float: right; + margin-right: 0em; +} + +#bottom { + position: relative; + bottom: 0px; + left: -0.5em; + width: 100%; + padding-right: 1em; + height: 1.3em; + text-align: right; + color: #ffe4aa; + background-color: #400827; + border-color: #260314; + border-style: solid; + border-width: 5px 0px 0px 0px; +} + +#menu-top-par { + margin-top: 0.5em; + margin-bottom: 0em; +} + +#menu-list { + list-style: none; + padding: 0em; + margin: 0.25em; + margin-bottom: 0.5em; +} + +#topbar a { + font-weight: bold; + text-decoration: none; + color: #ffe4aa; + width: 100%; +} + +#topbar a:hover { + color: #b5bf8f; +} + + +/* Content */ + +.game_list { + font-weight: bold; +} + +.game_list a { + font-weight: normal; +} + +#main { + margin-top: 2.5em; + color: #260314; + background-color: #ffe4aa; + margin-left: 1em; + margin-right: 1em; + padding: 1em; + min-height: 100%; + padding-bottom: 2em; + border: 1px solid #260314; + border-bottom: 0px; +} + +#main a, #main a:link, #main a:active, #main a:visited { + color: #260314; + text-decoration: underline; +} + +#main a:hover { + color: #400827; + text-decoration: none; +} + + +#opponents { + display: none; + position: absolute; + left: 19em; + top: 3.5em; + min-width: 20em; + color: #ffe4aa; + background-color: #400827; + font-weight: bold; + padding: 1em; + border: 1px solid #260314; + z-index: 10; +} + +#opponents a, #opponents a:link, #opponents a:active, #opponents a:visited { + color: #ffe4aa; + text-decoration: none; + font-weight: bold; +} + +#opponents a:hover { + color: #b5bf8f; +} + +#opponents-list { + list-style: square; + margin-top: 0.5em; +} + +.opponents-list-elem { + /* margin-left: -1em; */ +} + +#opponents-next { + position: absolute; + right: 1em; + bottom: 0.25em; +} + +#opponents-prev { + position: absolute; + left: 1em; + bottom: 0.25em; + display: none; +} + +#welcome { + text-align: justify; + margin-top: 1em; +} + +#welcome-top { + font-size: 1.2em; + font-weight: bold; + padding-left: 1.25em; +} + +.short { + max-width: 40em; +} + +#features-list { + list-style: square; +} + +#game-title { + font-size: 1.2em; + font-weight: bold; + margin-top: 1em; + margin-bottom: 2em; +} + +#game-disp { + position: relative; + display: none; +} + +#game-desc { + text-align: justify; + display: none; + width: 29em; + height: 19em; + margin-right: 1em; + padding-right: 1em; + border-right: 1px solid #260314; +} + +#board { + position: absolute; + left: 9em; + padding-right: 1em; + top: 0px; + width: 20em; + height: 19em; + border-right: 1px solid #260314; +} + +#working { + position: absolute; + left: 4.5em; + top: 7em; + width: 10em; + text-align: center; + font-weight: bold; + color: #ffe4aa; + background-color: #400827; + display: none; + padding: 1em; +} + +#opening { + position: absolute; + left: 10em; + top: 7em; + width: 16em; + text-align: center; + font-weight: bold; + color: #ffe4aa; + background-color: #400827; + display: none; + padding: 1em; +} + +#move { + position: absolute; + left: 0px; + top: 0px; +} + +#play-no-div { + padding-bottom: 0.5em; + padding-left: 1em; +} + +#cur-move, #cur-player { + padding-left: 1em; + margin-top: 0.5em; + margin-bottom: 0.5em; +} + +#mk-move { + padding-left: 0em; +} + +#plays { + display: none; + padding-left: 1em; +} + +#plays-list { + list-style: none; + margin-top: 0.25em; +} + +.plays-list-elem { + margin-left: -1.5em; +} + +.plays-list-elem a { + margin-right: 0.5em; +} + +.plays-list-elem .thumb { + position: relative; + top: 5px; + left: 0px; + border: 1px solid #260314; +} + + + +/* SVG styling */ +.board-outline { + fill: #b5bf8f; + stroke: #260314; + stroke-width: 10px; +} + +.model-elem { + fill: #b5bf8f; + stroke: #260314; + stroke-width: 3px; +} + +.model-elem-highlight { + fill: #ffe4aa; + stroke: #400827; + stroke-width: 3px; +} + +.model-pred-P { + fill: #400827; + stroke: #260314; + stroke-width: 5px; +} + +.model-pred-Q { + fill: #b5bf8f; + stroke: #260314; +} + +.model-pred-C { + fill: #ffe4aa; + stroke: #260314; + stroke-width: 3px; +} + +.model-pred-R { + fill: #400827; + stroke: #260314; + stroke-width: 3px; +} + +.model-pred-W { + fill: #ffe4aa; + stroke: #260314; + stroke-width: 3px; +} + +.model-pred-B { + fill: #400827; + stroke: #260314; + stroke-width: 3px; +} + +.model-edge-E { + fill: #260314; + stroke: #260314; + stroke-width: 3px; +} + +.chessW .chess-path-A { + opacity:1; + fill:#ffe4aa; + fill-opacity:1; + fill-rule:nonzero; + stroke:#260314; + stroke-width:1.5; + stroke-linecap:round; + stroke-linejoin:miter; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-dashoffset:10; + stroke-opacity:1; +} + +.chessB .chess-path-A { + opacity:1; + fill:#400827; + fill-opacity:1; + fill-rule:nonzero; + stroke:#260314; + stroke-width:1.5; + stroke-linecap:round; + stroke-linejoin:miter; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-dashoffset:10; + stroke-opacity:1; +} + +.chessW .chess-path-B { + opacity:1; + fill:#ffe4aa; + fill-opacity:1; + fill-rule:evenodd; + stroke:#260314; + stroke-width:1.5; + stroke-linecap:round; + stroke-linejoin:round; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-opacity:1; +} + +.chessB .chess-path-B { + opacity:1; + fill: #400827; + fill-opacity:1; + fill-rule:evenodd; + stroke:#260314; + stroke-width:1.5; + stroke-linecap:round; + stroke-linejoin:round; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-opacity:1; +} + +.chessW .chess-path-Bx { + opacity:1; + fill:#ffe4aa; + fill-opacity:1; + fill-rule:evenodd; + stroke:#260314; + stroke-width:1.5; + stroke-linecap:round; + stroke-linejoin:round; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-opacity:1; +} + +.chessB .chess-path-Bx { + opacity:1; + fill: #ffe4aa; + fill-opacity:1; + fill-rule:evenodd; + stroke: #400827; + stroke-width:1.5; + stroke-linecap:round; + stroke-linejoin:round; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-opacity:1; +} + +.chessW .chess-path-C { + opacity:1; + fill:#400827; + fill-opacity:1; + stroke:#260314; + stroke-width:1.5; + stroke-linecap:round; + stroke-linejoin:round; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-opacity:1; +} + +.chessB .chess-path-C { + opacity:1; + fill:#ffe4aa; + fill-opacity:1; + stroke:#ffe4aa; + stroke-width:1.5; + stroke-linecap:round; + stroke-linejoin:round; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-opacity:1; +} + +.chessW .chess-path-D { + fill: #ffe4aa; + fill-opacity: 0.75; + fill-rule:evenodd; + stroke: #260314; + stroke-width:1; + stroke-linecap:round; + stroke-linejoin:mitter; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-opacity:1; +} + +.chessB .chess-path-D { + fill: #400827; + fill-opacity: 0.75; + fill-rule:evenodd; + stroke: #ffe4aa; + stroke-width:1; + stroke-linecap:round; + stroke-linejoin:mitter; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-opacity:1; +} Deleted: trunk/Toss/WebClient/TossConnect.js =================================================================== --- trunk/Toss/WebClient/TossConnect.js 2010-12-18 00:52:28 UTC (rev 1253) +++ trunk/Toss/WebClient/TossConnect.js 2010-12-18 17:49:52 UTC (rev 1254) @@ -1,219 +0,0 @@ -// JavaScript Toss Module -- Connect (basic Toss Server connection routines) - -var UNAME = ""; - -var MODEL_MAXX = 0.0; -var MODEL_MINX = 0.0; -var MODEL_MAXY = 0.0; -var MODEL_MINY = 0.0; -var MODEL_WIDTH = 0.0; -var MODEL_HEIGHT = 0.0; -var SVG_WIDTH = 500; -var SVG_HEIGHT = 500; -var SVG_MARGINX = 50; -var SVG_MARGINY = 50; -var VIEW_WIDTH = "19em"; -var VIEW_HEIGHT = "19em"; -var VIEW_MIRROR = 0; - -var GAME_NAME = ""; // name of current game, e.g. "Breakthrough" -var ELEMS = []; // used to store the list of elements -var ELEM_POS = {}; // positions of elements -var RELS = []; // relations -var SUGGESTED_ELEM_SIZEX = 25; // suggested size of elements -var SUGGESTED_ELEM_SIZEY = 25; // suggested size of elements - -var CACHED_MOVES = "" - -var DIM_STR = "" -var ELEM_STR = "" -var RELS_STR = "" -var MOVES_STR = "" - - -// Helper function: sign of a number. -function sign (x) { - if (x > 0.01) { return (1); } - else if (x < -0.01) { return (-1); } - else { return (0); } -} - -// Clears cached moves. -function clear_move_cache () { - CACHED_MOVES = ""; -} - -function set_info (info) { - var res_arr = []; - res_arr = info.split("$"); - if (res_arr.length != 4) { return (false); } - DIM_STR = res_arr[0]; - ELEM_STR = res_arr[1]; - RELS_STR = res_arr[2]; - MOVES_STR = res_arr[3]; - var dim = strip('(', ')', DIM_STR).split(','); - MODEL_MAXX = parseFloat(strip(' ', ' ', dim[0])); - MODEL_MINX = parseFloat(strip(' ', ' ', dim[1])); - MODEL_MAXY = parseFloat(strip(' ', ' ', dim[2])); - MODEL_MINY = parseFloat(strip(' ', ' ', dim[3])); - MODEL_WIDTH = Math.max (SVG_WIDTH / 100, (MODEL_MAXX - MODEL_MINX)); - MODEL_HEIGHT = Math.max (SVG_HEIGHT / 100, (MODEL_MAXY - MODEL_MINY)); - - return (true); -} - -// Send [msg] to server and return response text. -function sync_server_msg (msg) { - var xml_request = new XMLHttpRequest (); - xml_request.open ('POST', 'TossHandler.py', false); - xml_request.setRequestHeader ('Content-Type', - 'application/x-www-form-urlencoded; charset=UTF-8'); - xml_request.send (msg); - resp = xml_request.responseText; - if (resp.indexOf ("MOD_PYTHON ERROR") > -1) { - alert (resp.substring(resp.indexOf("Traceback"))); - return (""); - } - return (resp) -} - -// Simple encryption -function crypt (s) { - var c = Crypto.SHA256(s, true); - var d = c.replace("#", "$"); - return (d.replace(" ", "$")); -} - -// Send [msg] to server attaching prefix '[cmd]#' and return response text. -function srv (cmd, msg) { - return (sync_server_msg (cmd + '#' + msg)); -} - -// Strip [c1] and [c2] from beginning and end of [str]. -function strip (c1, c2, str) { - if (str.length == 0) return (str); - var i = 0; var j = 0; - for (i = 0; i < str.length; i++) { - if (str.charAt(i) != c1 && str.charAt(i) != c2) break; - } - for (j = str.length - 1; j > -1; j--) { - if (str.charAt(j) != c1 && str.charAt(j) != c2) break; - } - if (i > j) { return ("") }; - return (str.substring(i, j+1)); -} - -// Convert a string [str] representing python list to array and return it. -// WARNING: we use [sep] as separator, it must not occur in list elements! -funct... [truncated message content] |
From: <luk...@us...> - 2010-12-18 00:52:34
|
Revision: 1253 http://toss.svn.sourceforge.net/toss/?rev=1253&view=rev Author: lukaszkaiser Date: 2010-12-18 00:52:28 +0000 (Sat, 18 Dec 2010) Log Message: ----------- Store only models in WebClient plays, each game only once. Chess works reasonably now. Modified Paths: -------------- trunk/Toss/Arena/Arena.ml trunk/Toss/Arena/Arena.mli trunk/Toss/Arena/ArenaParser.mly trunk/Toss/Play/Server.ml trunk/Toss/WebClient/README trunk/Toss/WebClient/TossDefaultStyle.js trunk/Toss/WebClient/TossHandler.py trunk/Toss/WebClient/TossMain.js trunk/Toss/WebClient/TossStyle.css trunk/Toss/WebClient/Wrapper.py trunk/Toss/WebClient/index.html Modified: trunk/Toss/Arena/Arena.ml =================================================================== --- trunk/Toss/Arena/Arena.ml 2010-12-16 22:53:03 UTC (rev 1252) +++ trunk/Toss/Arena/Arena.ml 2010-12-18 00:52:28 UTC (rev 1253) @@ -173,6 +173,9 @@ (List.length old_rules) (List.length old_locs); ); (* }}} *) + let rev_models_at_end l = + let m, n = List.partition (function StateStruc _ -> true | _ -> false) l in + n @ (List.rev m) in let rules, locations, players, defined_rels, state, time, cur_loc, data = List.fold_right (fun def (rules, locations, players, defined_rels, @@ -203,7 +206,7 @@ | StateData more_data -> (rules, locations, players, defined_rels, state, time, cur_loc, data @ more_data) - ) defs ([], [], players, defined_rels, + ) (rev_models_at_end defs) ([], [], players, defined_rels, state, time, cur_loc, data) in (* {{{ log entry *) if !debug_level > 2 then ( @@ -469,6 +472,7 @@ | SetTime of float * float (* Set time step and time *) | GetTime (* Get time step and time *) | SetState of game_state (* Set the full state *) + | GetModel (* Return the current model*) | GetState (* Return the state *) @@ -870,4 +874,5 @@ (state, string_of_float (ts) ^ " / " ^ string_of_float (t)) | SetState s -> (s, "STATE SET") + | GetModel -> (state, Structure.sprint state.struc) | GetState -> (state, state_str state) Modified: trunk/Toss/Arena/Arena.mli =================================================================== --- trunk/Toss/Arena/Arena.mli 2010-12-16 22:53:03 UTC (rev 1252) +++ trunk/Toss/Arena/Arena.mli 2010-12-18 00:52:28 UTC (rev 1253) @@ -175,6 +175,7 @@ | SetTime of float * float (** Set time step and time *) | GetTime (** Get time step and time *) | SetState of game_state (** Set the full state *) + | GetModel (** Return the model *) | GetState (** Return the state *) val handle_request : game_state -> request -> game_state * string Modified: trunk/Toss/Arena/ArenaParser.mly =================================================================== --- trunk/Toss/Arena/ArenaParser.mly 2010-12-16 22:53:03 UTC (rev 1252) +++ trunk/Toss/Arena/ArenaParser.mly 2010-12-18 00:52:28 UTC (rev 1253) @@ -135,6 +135,7 @@ | GET_CMD SIG_MOD id_int { GetArity ($3) } | SET_CMD STATE_SPEC gs=game_state { SetState gs } | GET_CMD STATE_SPEC { GetState } + | GET_CMD MODEL_SPEC { GetModel } | ADD_CMD ELEM_MOD struct_location { AddElem ($3) } | ADD_CMD REL_MOD Modified: trunk/Toss/Play/Server.ml =================================================================== --- trunk/Toss/Play/Server.ml 2010-12-16 22:53:03 UTC (rev 1252) +++ trunk/Toss/Play/Server.ml 2010-12-18 00:52:28 UTC (rev 1253) @@ -117,6 +117,7 @@ | Arena.SetTime _ -> false (* TODO: rethink when working on dyns *) | Arena.GetTime -> false | Arena.SetState _ -> true + | Arena.GetModel -> false | Arena.GetState -> false exception Found of int Modified: trunk/Toss/WebClient/README =================================================================== --- trunk/Toss/WebClient/README 2010-12-16 22:53:03 UTC (rev 1252) +++ trunk/Toss/WebClient/README 2010-12-18 00:52:28 UTC (rev 1253) @@ -19,12 +19,11 @@ TODO: - - better register html - - back button handler (reload), enter for login - - enable google (or other) analytics - - refresh (async?) plays in which the other player moves + - better register html and user table - move interface: first click all, second click toggle, if one - confirm msg - after the above: remove left-of-board div, confirm in the middle - after the above: show game result in the middle / instead of move - - option to give up game and offer a draw - sort plays by who's turn it is + - option to give up game and offer a draw + - enable google (or other) analytics + - refresh (async?) plays in which the other player moves Modified: trunk/Toss/WebClient/TossDefaultStyle.js =================================================================== --- trunk/Toss/WebClient/TossDefaultStyle.js 2010-12-16 22:53:03 UTC (rev 1252) +++ trunk/Toss/WebClient/TossDefaultStyle.js 2010-12-18 00:52:28 UTC (rev 1253) @@ -38,14 +38,14 @@ var DEFbishop = '<g transform="translate(-22.5,-22.5)"> \ <path \ d="M 9,36 C 12.385,35.028 19.115,36.431 22.5,34 C 25.885,36.431 32.615,35.028 36,36 C 36,36 37.646,36.542 39,38 C 38.323,38.972 37.354,38.986 36,38.5 C 32.615,37.528 25.885,38.958 22.5,37.5 C 19.115,38.958 12.385,37.528 9,38.5 C 7.6459,38.986 6.6771,38.972 6,38 C 7.3541,36.055 9,36 9,36 z " \ - style="stroke-linecap:butt;" class="chess-path-B" /> \ + style="stroke-linecap:butt;" class="chess-path-Bx" /> \ <path \ d="M 15,32 C 17.5,34.5 27.5,34.5 30,32 C 30.5,30.5 30,30 30,30 C 30,27.5 27.5,26 27.5,26 C 33,24.5 33.5,14.5 22.5,10.5 C 11.5,14.5 12,24.5 17.5,26 C 17.5,26 15,27.5 15,30 C 15,30 14.5,30.5 15,32 z " \ style="stroke-linecap:butt;" class="chess-path-B" /> \ <path \ d="M 25 10 A 2.5 2.5 0 1 1 20,10 A 2.5 2.5 0 1 1 25 10 z" \ transform="translate(0,-2)" \ - style="stroke-linecap:butt;" class="chess-path-B" /> \ + style="stroke-linecap:butt;" class="chess-path-Bx" /> \ <path \ d="M 17.5,26 L 27.5,26" \ style="stroke-linecap:butt;" class="chess-path-D" /> \ @@ -63,10 +63,10 @@ var DEFrook = '<g transform="translate(-22.5,-22.5)"> \ <path \ d="M 9,39 L 36,39 L 36,36 L 9,36 L 9,39 z " \ - style="stroke-linecap:butt;" class="chess-path-B" /> \ + style="stroke-linecap:butt;" class="chess-path-Bx" /> \ <path \ d="M 12,36 L 12,32 L 33,32 L 33,36 L 12,36 z " \ - style="stroke-linecap:butt;" class="chess-path-B" /> \ + style="stroke-linecap:butt;" class="chess-path-Bx" /> \ <path \ d="M 11,14 L 11,9 L 15,9 L 15,11 L 20,11 L 20,9 L 25,9 L 25,11 L 30,11 L 30,9 L 34,9 L 34,14" \ style="stroke-linecap:butt;" class="chess-path-B" /> \ @@ -78,7 +78,7 @@ style="stroke-linecap:butt;" class="chess-path-B" /> \ <path \ d="M 31,29.5 L 32.5,32 L 12.5,32 L 14,29.5" \ - class="chess-path-B" /> \ + class="chess-path-Bx" /> \ <path \ d="M 11,14 L 34,14" \ class="chess-path-D" /> \ Modified: trunk/Toss/WebClient/TossHandler.py =================================================================== --- trunk/Toss/WebClient/TossHandler.py 2010-12-16 22:53:03 UTC (rev 1252) +++ trunk/Toss/WebClient/TossHandler.py 2010-12-18 00:52:28 UTC (rev 1253) @@ -10,7 +10,7 @@ TUID = "toss_id_05174_" def tmp_log (str): - file = open ("/tmp/th.log", 'w') + file = open ("/tmp/th.log", 'a') file.write (str) file.close() @@ -27,23 +27,37 @@ time.sleep (0.1) return (port) +def get_global_lock (db): + cur = db.cursor () + cur.execute ("update lock set locked='true' " + + " where locked='false' and tid='" + str(TUID) + "'") + db.commit () + if cur.rowcount == 1: + return + time.sleep (0.1) + get_global_lock (db) + +def release_global_lock (db): + db.execute ("update lock set locked='false' " + + " where locked='true' and tid='" + str(TUID) + "'") + db.commit () + def get_toss_port (db): + get_global_lock (db) free_ports = get_all_from_db (db, "ports", "locked='false'") if len(free_ports) == 0: fid = 0 for f in db.execute ("select count(*) from ports"): fid = int(f[0]) port = 8110+fid+1 - # WARNING: two proc can get same fid! Avoid by sqlite write-atomicity! db.execute ("insert into ports(port, locked) values (?, ?)", (port, 'true')) - db.commit () + release_global_lock (db) open_toss_server (port) return (port) (port, _) = free_ports[0] db.execute ("update ports set locked='true' where port=" + str(port)) - # This could give same port to 2 proc (1st line). Avoid by sql-write! - db.commit () + release_global_lock (db) return (port) def release_toss_port (db, port): @@ -84,7 +98,8 @@ (_, toss) = res[0] client.open_from_str (toss) info = get_game_info (client) - db_cur_insert (db, game, p1, p2, pid, move, toss, info, "") + model = client.get_model () + db_cur_insert (db, game, p1, p2, pid, move, model, info, "") return (info) def game_select_s (g, p1, p2, pid, m): @@ -102,10 +117,12 @@ select_s = game_select_s (g, p1, p2, pid, m) old_res = get_all_from_db (db, "cur_states", select_s) (_, _, _, _, _, old_toss, old_info, old_svg) = old_res[0] - client.open_from_str (old_toss) + res = get_all_from_db (db, "games", "game='" + g + "'") + (_, game_toss) = res[0] + client.open_from_str (game_toss + "\n MODEL " + old_toss) (move1, move2, move3) = move_tup client.make_move (move1, move2, move3) - new_toss = client.get_state () + new_toss = client.get_model () new_info = get_game_info (client) db.execute ("delete from cur_states where " + select_s) db_old_insert (db, g, p1, p2, pid, m, old_toss, old_info, old_svg) Modified: trunk/Toss/WebClient/TossMain.js =================================================================== --- trunk/Toss/WebClient/TossMain.js 2010-12-16 22:53:03 UTC (rev 1252) +++ trunk/Toss/WebClient/TossMain.js 2010-12-18 00:52:28 UTC (rev 1253) @@ -161,8 +161,8 @@ } function play_click (game, play_id, pi) { - list_plays (game) - game_click (game) + list_plays (game); + game_click (game); document.getElementById ("game-title").innerHTML = game; document.getElementById("game-disp").style.display = "block"; document.getElementById("play-number").innerHTML = "" + play_id; @@ -324,6 +324,8 @@ UNAME = un document.getElementById("topuser").innerHTML = "Welcome " + un; document.getElementById("loginform").style.display = "none"; + document.getElementById("topright-register").style.display = "none"; + document.getElementById("topright").style.display = "inline"; document.getElementById("welcome").style.display = "none"; document.getElementById("plays").style.display = "block"; list_plays ("Breakthrough"); @@ -333,6 +335,18 @@ list_plays ("Tic-Tac-Toe"); } +// Clear view +function clear_view () { + document.getElementById("loginform").style.display = "inline"; + document.getElementById("topright-register").style.display = "inline"; + document.getElementById("topright").style.display = "none"; + document.getElementById("topuser").innerHTML = ""; + document.getElementById("plays").style.display = "none"; + document.getElementById("game-title").style.display = "none"; + document.getElementById("game-disp").style.display = "none"; + document.getElementById("welcome").style.display = "block"; +} + function startup () { if (navigator.userAgent.indexOf('MSIE') !=-1) { document.getElementById("nosvg").style.display = "block"; @@ -357,10 +371,5 @@ // Logout function logout () { - document.getElementById("loginform").style.display = "inline"; - document.getElementById("topuser").innerHTML = ""; - document.getElementById("plays").style.display = "none"; - document.getElementById("game-title").style.display = "none"; - document.getElementById("game-disp").style.display = "none"; - document.getElementById("welcome").style.display = "block"; + clear_view (); } Modified: trunk/Toss/WebClient/TossStyle.css =================================================================== --- trunk/Toss/WebClient/TossStyle.css 2010-12-16 22:53:03 UTC (rev 1252) +++ trunk/Toss/WebClient/TossStyle.css 2010-12-18 00:52:28 UTC (rev 1253) @@ -58,8 +58,14 @@ #topright { float: right; margin-right: 0em; + display: none; } +#topright-register { + float: right; + margin-right: 0em; +} + #bottom { position: relative; bottom: 0px; @@ -410,7 +416,7 @@ .chessB .chess-path-B { opacity:1; - fill:#400827; + fill: #400827; fill-opacity:1; fill-rule:evenodd; stroke:#260314; @@ -422,6 +428,34 @@ stroke-opacity:1; } +.chessW .chess-path-Bx { + opacity:1; + fill:#ffe4aa; + fill-opacity:1; + fill-rule:evenodd; + stroke:#260314; + stroke-width:1.5; + stroke-linecap:round; + stroke-linejoin:round; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-opacity:1; +} + +.chessB .chess-path-Bx { + opacity:1; + fill: #ffe4aa; + fill-opacity:1; + fill-rule:evenodd; + stroke: #400827; + stroke-width:1.5; + stroke-linecap:round; + stroke-linejoin:round; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-opacity:1; +} + .chessW .chess-path-C { opacity:1; fill:#400827; Modified: trunk/Toss/WebClient/Wrapper.py =================================================================== --- trunk/Toss/WebClient/Wrapper.py 2010-12-16 22:53:03 UTC (rev 1252) +++ trunk/Toss/WebClient/Wrapper.py 2010-12-18 00:52:28 UTC (rev 1253) @@ -117,6 +117,9 @@ def get_state (self): return (self.msg ("GET STATE")) + def get_model (self): + return (self.msg ("GET MODEL")) + def set_state (self, state): m = self.msg ("SET STATE " + state) return (m) Modified: trunk/Toss/WebClient/index.html =================================================================== --- trunk/Toss/WebClient/index.html 2010-12-16 22:53:03 UTC (rev 1252) +++ trunk/Toss/WebClient/index.html 2010-12-18 00:52:28 UTC (rev 1253) @@ -21,15 +21,17 @@ <form id="loginform" style="display: inline;"> Username: <input type="text" name="username" id="username" /> -Password: <input type="password" name="password" id="password" /> +Password: <input type="password" name="password" id="password" + onkeypress="if (window.event && window.event.keyCode == 13) { login () }" /> <a id="login" href="#" onclick="login()">Login</a> - -(<a href="register.html">Register</a>) </form> <span id="topright"> <a id="logout" href="#" onclick="logout()">Logout</a> </span> +<span id="topright-register"> + <a href="register.html">Register</a> +</span> </div> </div> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-16 22:53:10
|
Revision: 1252 http://toss.svn.sourceforge.net/toss/?rev=1252&view=rev Author: lukaszkaiser Date: 2010-12-16 22:53:03 +0000 (Thu, 16 Dec 2010) Log Message: ----------- WebClient cleanup, next step. Modified Paths: -------------- trunk/Toss/WebClient/README trunk/Toss/WebClient/TossConnect.js trunk/Toss/WebClient/TossDefaultStyle.js trunk/Toss/WebClient/TossHandler.py trunk/Toss/WebClient/TossMain.js trunk/Toss/WebClient/TossStyle.css trunk/Toss/WebClient/Wrapper.py trunk/Toss/WebClient/make_db.py trunk/Toss/WebClient/register.html Modified: trunk/Toss/WebClient/README =================================================================== --- trunk/Toss/WebClient/README 2010-12-15 00:02:30 UTC (rev 1251) +++ trunk/Toss/WebClient/README 2010-12-16 22:53:03 UTC (rev 1252) @@ -19,7 +19,8 @@ TODO: - - redo TossServer calls and caching + - better register html + - back button handler (reload), enter for login - enable google (or other) analytics - refresh (async?) plays in which the other player moves - move interface: first click all, second click toggle, if one - confirm msg Modified: trunk/Toss/WebClient/TossConnect.js =================================================================== --- trunk/Toss/WebClient/TossConnect.js 2010-12-15 00:02:30 UTC (rev 1251) +++ trunk/Toss/WebClient/TossConnect.js 2010-12-16 22:53:03 UTC (rev 1252) @@ -51,6 +51,14 @@ ELEM_STR = res_arr[1]; RELS_STR = res_arr[2]; MOVES_STR = res_arr[3]; + var dim = strip('(', ')', DIM_STR).split(','); + MODEL_MAXX = parseFloat(strip(' ', ' ', dim[0])); + MODEL_MINX = parseFloat(strip(' ', ' ', dim[1])); + MODEL_MAXY = parseFloat(strip(' ', ' ', dim[2])); + MODEL_MINY = parseFloat(strip(' ', ' ', dim[3])); + MODEL_WIDTH = Math.max (SVG_WIDTH / 100, (MODEL_MAXX - MODEL_MINX)); + MODEL_HEIGHT = Math.max (SVG_HEIGHT / 100, (MODEL_MAXY - MODEL_MINY)); + return (true); } @@ -162,31 +170,9 @@ // Open [file_name] on Toss Server and get info. -function toss_open_game (game_name) { - var info = srv ("OPENGAME", game_name); - set_info (info); - var dim_msg = DIM_STR; - var dim = strip('(', ')', dim_msg).split(','); - MODEL_MAXX = parseFloat(strip(' ', ' ', dim[0])); - MODEL_MINX = parseFloat(strip(' ', ' ', dim[1])); - MODEL_MAXY = parseFloat(strip(' ', ' ', dim[2])); - MODEL_MINY = parseFloat(strip(' ', ' ', dim[3])); - MODEL_WIDTH = Math.max (SVG_WIDTH / 100, (MODEL_MAXX - MODEL_MINX)); - MODEL_HEIGHT = Math.max (SVG_HEIGHT / 100, (MODEL_MAXY - MODEL_MINY)); -} - -// Open [file_name] on Toss Server and get info. function toss_open_db (file_name_params) { - var info = srv ("OPEN_DB", 'c, ' + file_name_params); + var info = srv ("OPEN_DB", file_name_params); set_info (info); - var dim_msg = DIM_STR; - var dim = strip('(', ')', dim_msg).split(','); - MODEL_MAXX = parseFloat(strip(' ', ' ', dim[0])); - MODEL_MINX = parseFloat(strip(' ', ' ', dim[1])); - MODEL_MAXY = parseFloat(strip(' ', ' ', dim[2])); - MODEL_MINY = parseFloat(strip(' ', ' ', dim[3])); - MODEL_WIDTH = Math.max (SVG_WIDTH / 100, (MODEL_MAXX - MODEL_MINX)); - MODEL_HEIGHT = Math.max (SVG_HEIGHT / 100, (MODEL_MAXY - MODEL_MINY)); } Modified: trunk/Toss/WebClient/TossDefaultStyle.js =================================================================== --- trunk/Toss/WebClient/TossDefaultStyle.js 2010-12-15 00:02:30 UTC (rev 1251) +++ trunk/Toss/WebClient/TossDefaultStyle.js 2010-12-16 22:53:03 UTC (rev 1252) @@ -238,9 +238,10 @@ document.getElementById("svg").appendChild(f); } else { add_svg ("circle", - [["cx", pos[0]], ["cy", pos[1]], ["r", SUGGESTED_ELEM_SIZEX - 10], + [["cx", pos[0]], ["cy", pos[1]], ["r", SUGGESTED_ELEM_SIZEX - 12], ["id", "pred_" + args[0] + "_" + rel_name], ["class", "model-pred-" + rel_name], + ["stroke-width", (SUGGESTED_ELEM_SIZEX / 10) + 2], ["onclick", ("handle_elem_click('" + args[0] + "')")]]); } } Modified: trunk/Toss/WebClient/TossHandler.py =================================================================== --- trunk/Toss/WebClient/TossHandler.py 2010-12-15 00:02:30 UTC (rev 1251) +++ trunk/Toss/WebClient/TossHandler.py 2010-12-16 22:53:03 UTC (rev 1252) @@ -9,42 +9,26 @@ TUID = "toss_id_05174_" -db = None - def tmp_log (str): file = open ("/tmp/th.log", 'w') file.write (str) file.close() -def get_all_from_db (tbl, select_s): +def get_all_from_db (db, tbl, select_s): res = [] for r in db.execute("select * from " + tbl + " where " + select_s): res.append(r) return (res) -def is_toss_server (host, port): - """Simple server check - tries to get time from Toss server.""" - try: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.connect ((host, port)) - sock.send ("GET dynamics\n") - data = sock.recv(2048) - sock.close () - time = [s.strip() for s in data.split('/')] - (ts, t) = (float(time[0]), float(time[1])) - return (True) - except: - return (False) - def open_toss_server (port): args = ["/var/www/WebClient/TossServer", - "-s", "localhost", "-t", "600", "-p", str(port)] + "-s", "localhost", "-p", str(port)] server_proc = subprocess.Popen(args) time.sleep (0.1) return (port) -def get_toss_port (): - free_ports = get_all_from_db ("ports", "locked='false'") +def get_toss_port (db): + free_ports = get_all_from_db (db, "ports", "locked='false'") if len(free_ports) == 0: fid = 0 for f in db.execute ("select count(*) from ports"): @@ -62,40 +46,32 @@ db.commit () return (port) -def release_toss_port (port): +def release_toss_port (db, port): db.execute ("update ports set locked='false' where port=" + str(port)) db.commit () def cp (f1, f2): subprocess.call(["cp", f1, f2]) -def list_plays (game, player_id): +def list_plays (db, game, player_id): or_s = "(player1='" + player_id + "' or player2='" + player_id + "')" - plays = get_all_from_db ("cur_states", "game='" + game + "' and " + or_s) + plays = get_all_from_db (db, "cur_states", "game='"+ game + "' and " + or_s) def play_name (p): - (pid, g, p1, p2, move, toss, svg) = p + (pid, g, p1, p2, move, _, _, _) = p return ("/plays/" + str(g) + "_" + str(p1) + "_" + str(p2) + "_" + str(pid) + "_" + str(move)) return (str([play_name (p) for p in plays])) -def db_cur_insert (game, p1, p2, pid, move, toss, svg_str): - db.execute ("insert into cur_states(playid, game, player1, player2, move, toss, svg) values (?, ?, ?, ?, ?, ?, ?)", (pid, game, p1, p2, move, toss, svg_str)) +def db_cur_insert (db, game, p1, p2, pid, move, toss, info, svg_str): + db.execute ("insert into cur_states(playid, game, player1, player2, move, toss, info, svg) values (?, ?, ?, ?, ?, ?, ?, ?)", + (pid, game, p1, p2, move, toss, info, svg_str)) db.commit () -def db_old_insert (game, p1, p2, pid, move, toss, svg_str): - db.execute ("insert into old_states(playid, game, player1, player2, move, toss, svg) values (?, ?, ?, ?, ?, ?, ?)", (pid, game, p1, p2, move, toss, svg_str)) +def db_old_insert (db, game, p1, p2, pid, move, toss, info, svg_str): + db.execute ("insert into old_states(playid, game, player1, player2, move, toss, info, svg) values (?, ?, ?, ?, ?, ?, ?, ?)", + (pid, game, p1, p2, move, toss, info, svg_str)) db.commit () -def new_play (game, p1, p2, pid, move, svg_str): - res = get_all_from_db ("games", "game='" + game + "'") - (_, toss) = res[0] - db_cur_insert (game, p1, p2, pid, move, toss, svg_str) - return ("ok") - -def game_select_s (g, p1, p2, pid, m): - return("game='" + g + "' and player1='" + p1 + "' and player2='" + p2 + - "' and playid=" + pid + " and move=" + m) - def get_game_info (client): dim_s = str(client.model.get_dim()) model_s = str(client.model.get_elems_with_pos()) @@ -103,56 +79,63 @@ moves_s = str(client.cur_moves()) return (dim_s + "$" + model_s + "$" + rels_s + "$" + moves_s) -def open_db (client, game, p1, p2, pid, move): - select_s = game_select_s (game, p1, p2, pid, move) - res = get_all_from_db ("cur_states", select_s) - (_, _, _, _, _, toss, _) = res[0] - client.open_from_str (toss) - return (get_game_info (client)) - -def open_game (client, game): - res = get_all_from_db ("games", "game='" + game + "'") +def new_play (db, client, game, p1, p2, pid, move): + res = get_all_from_db (db, "games", "game='" + game + "'") (_, toss) = res[0] client.open_from_str (toss) - return (get_game_info (client)) + info = get_game_info (client) + db_cur_insert (db, game, p1, p2, pid, move, toss, info, "") + return (info) -def move_play (client, move_tup, g, p1, p2, pid, m): - open_db (client, g, p1, p2, pid, m) +def game_select_s (g, p1, p2, pid, m): + return("game='" + g + "' and player1='" + p1 + "' and player2='" + p2 + + "' and playid=" + pid + " and move=" + m) + +def open_db (db, game, p1, p2, pid, move): + select_s = game_select_s (game, p1, p2, pid, move) + res = get_all_from_db (db, "cur_states", select_s) + (_, _, _, _, _, _, info, _) = res[0] + return (info) + + +def move_play (db, client, move_tup, g, p1, p2, pid, m): + select_s = game_select_s (g, p1, p2, pid, m) + old_res = get_all_from_db (db, "cur_states", select_s) + (_, _, _, _, _, old_toss, old_info, old_svg) = old_res[0] + client.open_from_str (old_toss) (move1, move2, move3) = move_tup client.make_move (move1, move2, move3) new_toss = client.get_state () - select_s = game_select_s (g, p1, p2, pid, m) - old_res = get_all_from_db ("cur_states", select_s) - (_, _, _, _, _, old_toss, old_svg) = old_res[0] + new_info = get_game_info (client) db.execute ("delete from cur_states where " + select_s) - db_old_insert (g, p1, p2, pid, m, old_toss, old_svg) - db_cur_insert (g, p1, p2, pid, int(m) + 1, new_toss, "") - return (get_game_info (client)) + db_old_insert (db, g, p1, p2, pid, m, old_toss, old_info, old_svg) + db_cur_insert (db, g, p1, p2, pid, int(m) + 1, new_toss, new_info, "") + return (new_info) -def upd_svg (g, p1, p2, pid, m, svg_s): +def upd_svg (db, g, p1, p2, pid, m, svg_s): select_s = game_select_s (g, p1, p2, pid, m) db.execute ("update cur_states set svg='" + svg_s + "' where " + select_s) db.commit () -def passwd_from_db (uid): - res = get_all_from_db ("passwd", "id='" + uid + "'") +def passwd_from_db (db, uid): + res = get_all_from_db (db, "passwd", "id='" + uid + "'") if len(res) > 1: raise Exception ("db", "multiple passwords for " + uid) if len(res) == 0: return (None) (uid, passwd) = res[0] return (str(passwd)) -def confirm_username (req): +def confirm_username (db, req): cookies = Cookie.get_cookies(req) if not (cookies.has_key(TUID + 'username')): return "" if not (cookies.has_key(TUID + 'passphrase')): return "" uid = cookies[TUID + 'username'].value pwd1 = cookies[TUID + 'passphrase'].value - pwd2 = passwd_from_db (uid) + pwd2 = passwd_from_db (db, uid) if (pwd1 != pwd2): return "" return (uid) -def login_user (req, uid, pwd): - db_pwd = passwd_from_db (uid) +def login_user (db, req, uid, pwd): + db_pwd = passwd_from_db (db, uid) if not db_pwd: return ("no such user registered") if (pwd != db_pwd): return ("wrong password") t = time.time() + 3600; @@ -162,23 +145,22 @@ Cookie.add_cookie(req, cookie2) return ("OK") -def register_user (uid, pwd): - if passwd_from_db (uid): return (False) +def register_user (db, uid, pwd): + if passwd_from_db (db, uid): return (False) db.execute ("insert into passwd(id, passwd) values (?, ?)", (uid, pwd)) db.commit () return (True) -def get_free_id (): +def get_free_id (db): fid = 0 for f in db.execute ("select count(*) from cur_states"): fid = int(f[0]) return (fid + 1) def handler(req): - global db req.content_type = "text/plain" db = sqlite3.connect(DB_FILE) - usr = confirm_username (req) + usr = confirm_username (db, req) msg = req.read () #tmp_log(msg) cmd, sep, data = msg.partition('#') @@ -187,14 +169,14 @@ return apache.OK if cmd == "REGISTER": uname, sep, pwd = data.partition(' ') - if register_user (uname, pwd): + if register_user (db, uname, pwd): req.write("Registration successful for " + uname) return apache.OK req.write("Registration failed, username " + uname + " already in use.") return apache.OK if cmd == "LOGIN": uname, sep, pwd = data.partition(' ') - res = login_user (req, uname, pwd) + res = login_user (db, req, uname, pwd) if res == "OK": req.write("OK") return apache.OK @@ -206,26 +188,18 @@ Cookie.add_cookie(req, cookie) req.write ("user logged out: " + usr + ".") return apache.OK - if cmd == "LIST_PLAYS": - res = eval (cmd.lower() + "(" + data + ")") - req.write(str(res)) - return apache.OK if cmd == "FREEID": - req.write(str(get_free_id ())) + req.write(str(get_free_id (db))) return apache.OK - if cmd == "OPENGAME": - port = get_toss_port () - c = SystemClient ("localhost", port) - res = open_game(c, data) - release_toss_port (port) + if (cmd == "LIST_PLAYS") or (cmd == "OPEN_DB") or (cmd == "UPD_SVG"): + res = eval (cmd.lower() + "(db, " + data + ")") req.write(str(res)) return apache.OK - if ((cmd == "OPEN_DB") or (cmd == "UPD_SVG") or - (cmd == "NEW_PLAY") or (cmd == "MOVE_PLAY")): - port = get_toss_port () + if (cmd == "NEW_PLAY") or (cmd == "MOVE_PLAY"): + port = get_toss_port (db) c = SystemClient ("localhost", port) - res = eval (cmd.lower() + "(" + data + ")") - release_toss_port (port) + res = eval (cmd.lower() + "(db, " + data + ")") + release_toss_port (db, port) req.write(str(res)) return apache.OK req.write("MOD_PYTHON ERROR ; Traceback: Unknown Toss Command! \n " + cmd) Modified: trunk/Toss/WebClient/TossMain.js =================================================================== --- trunk/Toss/WebClient/TossMain.js 2010-12-15 00:02:30 UTC (rev 1251) +++ trunk/Toss/WebClient/TossMain.js 2010-12-16 22:53:03 UTC (rev 1252) @@ -156,7 +156,6 @@ create_svg_box ("19em", "19em", 40, 40, "board"); } document.getElementById("opening").style.display = "block"; - toss_open_game (game); document.getElementById("opening").style.display = "none"; document.getElementById("game-disp").style.display = "block"; } @@ -312,10 +311,11 @@ document.getElementById("plays").style.left = "30em"; var p = [UNAME, opp_uid, FREE_PLAY_NO, 0]; PLAYS.push(p); - toss_open_game (GAME_NAME); + var fn = play_py_id (CUR_PLAY_I); + info = srv ("NEW_PLAY", "c, " + fn); + set_info(info); full_redraw (); - var fn = play_py_id (CUR_PLAY_I); - srv ("NEW_PLAY", fn + ", " + svg_string ()); + srv ("UPD_SVG", play_py_id(CUR_PLAY_I) + ", " + svg_string()); li = new_play_item (GAME_NAME, CUR_PLAY_I); document.getElementById("plays-list-" + GAME_NAME).appendChild(li); } @@ -346,7 +346,8 @@ function login () { un = document.getElementById('username').value; pwd = document.getElementById('password').value; - resp = sync_server_msg ("LOGIN#" + un + " " + crypt(pwd)); + ts = "toss##in$$some167S4lT_-"; + resp = sync_server_msg ("LOGIN#" + un + " " + crypt(ts + pwd)); if (resp == "OK") { setup_user (un) } else { Modified: trunk/Toss/WebClient/TossStyle.css =================================================================== --- trunk/Toss/WebClient/TossStyle.css 2010-12-15 00:02:30 UTC (rev 1251) +++ trunk/Toss/WebClient/TossStyle.css 2010-12-16 22:53:03 UTC (rev 1252) @@ -332,7 +332,6 @@ .model-pred-Q { fill: #b5bf8f; stroke: #260314; - stroke-width: 5px; } .model-pred-C { Modified: trunk/Toss/WebClient/Wrapper.py =================================================================== --- trunk/Toss/WebClient/Wrapper.py 2010-12-15 00:02:30 UTC (rev 1251) +++ trunk/Toss/WebClient/Wrapper.py 2010-12-16 22:53:03 UTC (rev 1252) @@ -14,8 +14,7 @@ self.p = pos def __str__ (self): - return ("Nbr " + (str (self.i)) + " pos " + (str (self.i)) + ": " + - (str (self.get_rels ()))) + return ("Nbr " + (str (self.i)) + " pos " + (str (self.i)) + ";") def id (self): return ("SOME MODEL", "SFX") @@ -27,43 +26,15 @@ return (" RULE " + (str (self.i)) + " LEFT ") return (" RULE " + (str (self.i)) + " RIGHT ") - def add_elem (self, el_x = 0.0, el_y = 0.0, el_vx = 0.0, el_vy = 0.0): - self.s.changes += 1 - el = self.s.msg ("ADD ELEM" + (self._pos ())) - self.set_elem_val (el, "x", el_x) - self.set_elem_val (el, "y", el_y) - self.set_elem_val (el, "vx", el_vx) - self.set_elem_val (el, "vy", el_vy) - return (el) - def get_elem_val (self, el_id, val): v = self.s.msg ("GET FUN" + (self._pos ()) + val + " " + (str (el_id))) return (float (v)) - def set_elem_val (self, el, val, x): - self.s.changes += 1 - m = self.s.msg ("SET FUN" + (self._pos()) + val + - " " + (str (el)) + " " + (repr (float (x)))) - return (m) - def get_elem_pos (self, el_id): x = self.get_elem_val (el_id, "x") y = self.get_elem_val (el_id, "y") return (x, y) - def set_elem_pos (self, el_id, x, y): - self.set_elem_val (el_id, "x", x) - self.set_elem_val (el_id, "y", y) - - def get_elem_velocity (self, el_id): - vx = self.get_elem_val (el_id, "vx") - vy = self.get_elem_val (el_id, "vy") - return (vx, vy) - - def set_elem_velocity (self, el_id, vx, vy): - self.set_elem_val (el_id, "vx", vx) - self.set_elem_val (el_id, "vy", vy) - def get_elems (self): m = self.s.msg ("GET ALLOF ELEM" + (self._pos ())) if len(m) < 1: @@ -84,42 +55,15 @@ sumx, sumy, l = sum(posx), sum(posy), len(pos) return (maxx, minx, maxy, miny, sumx / l, sumy / l) - def del_elem (self, el_id): - self.s.changes += 1 - m = self.s.msg ("DEL ELEM" + (self._pos ()) + (str (el_id))) - return (m) - def add_rel (self, rel, args): - rel_s = rel + "(" + ", ".join(str(v) for v in args) + ")" - self.s.changes += 1 - self.s.set_arity (rel, len(args)) - m = self.s.msg ("ADD REL" + (self._pos ()) + rel_s) - return (rel_s) + def get_rel_names_arities (self): + mrel = self.s.msg ("GET SIGNATURE REL" + (self._pos ())) + if len(mrel) < 1: return ([]) + pair_strs = [s.strip() for s in mrel.split (',')] + rels_ar_lst = [p.split(':') for p in pair_strs] + rels = [(rl[0].strip(), int (rl[1].strip())) for rl in rels_ar_lst] + return ([r for r in set(rels)]) - def get_rel_name (self, rel_id): - # Note that now rel_id is a string "Rel(args)" - return (rel_id[0:rel_id.find('(')]) - - def del_rel (self, rel_id): - self.s.changes += 1 - m = self.s.msg ("DEL REL" + (self._pos ()) + rel_id) - return (m) - - def get_rel_ids (self): - return ([i for (_, _, i) in self.get_rels ()]) - - def is_adjacent (self, el_id, rel_id): - # rel_id is Rel(Arg1,...,ArgN), just check if el_id = ArgK - args = [a.strip() for a in rel_id[rel_id.find('(')+1:-1].split(',')] - return (el_id in args) - - def is_in_rel (self, el_id, rel_name): - # it would be more efficient to add a request for it! - res = False - for args in self.get_rel (rel_name): - if el_id in args: res = True - return (res) - def get_rel (self, rel_name): m = self.s.msg ("GET ALLOF REL" + (self._pos ()) + rel_name) cur = m.find('{') @@ -128,18 +72,6 @@ tps = [ts.strip('{}() ') for ts in m[max(cur,par):].split(";")] return ([[t.strip() for t in ts.split(",")] for ts in tps]) - def get_rels (self, nodes = []): - """Return list of (rel, args, rel_id) for all rel(args) tuples.""" - sig = self.get_rel_names_arities () - if nodes == []: nodes = self.get_elems () - tuples = [] - def rel_str (rel, args): - return (rel + "(" + ", ".join(str(v) for v in args) + ")") - for (r, _) in sig: - tuples = [(r, a, rel_str (r, a)) for a in self.get_rel (r)] + tuples - return ([(n, args, i) for (n, args, i) in tuples - if set(args) <= set(nodes)]) - def get_rels_simple (self): """Return list of (rel, args, rel_id) for all rel(args) tuples.""" sig = self.get_rel_names_arities () @@ -148,17 +80,6 @@ tuples = [(r, a) for a in self.get_rel (r)] + tuples return ("; ".join ([str(t) for t in tuples])) - def set_arity (self, rel, i): - return (self.s.set_arity (rel, i)) - - def get_rel_names_arities (self): - mrel = self.s.msg ("GET SIGNATURE REL" + (self._pos ())) - if len(mrel) < 1: return ([]) - pair_strs = [s.strip() for s in mrel.split (',')] - rels_ar_lst = [p.split(':') for p in pair_strs] - rels = [(rl[0].strip(), int (rl[1].strip())) for rl in rels_ar_lst] - return ([r for r in set(rels)]) - def get_elems_with_pos (self): m = self.s.msg ("GET ALLOF ELEM" + (self._pos ())) if len(m) < 1: return ([]) @@ -175,14 +96,9 @@ """ self.host = host self.port = port - self.changes = 0 # increment on each change of model or rules - - # Initialize the model and the rules. self.model = ModelClient (self, ";MODEL", 0) - self.rule_names = self.__names_of_rules () - self.rules = [(ModelClient (self, i, 0), ModelClient (self, i, 1)) - for i in self.rule_names] + def __str__ (self): return ("System") @@ -198,29 +114,10 @@ sock.close () return (res.strip ()) - def __no_of_rules (self): - """Get number of rewrite rules from server.""" - names_msg = self.msg ("GET RULE") - if len(names_msg.strip()) < 1: return(0) - names = [s.strip() for s in names_msg.split (';')] - return (int (len(names))); - - def __names_of_rules (self): - """Get names of rewrite rules from server.""" - names_msg = self.msg ("GET RULE") - if len(names_msg.strip()) < 1: return([]) - return ([s.strip() for s in names_msg.split (';')]) - - def no_of_locs (self): - """Get number of game locations from server.""" - m = self.msg ("GET LOC").split("/") - return (int (m[1].strip())) - def get_state (self): return (self.msg ("GET STATE")) def set_state (self, state): - self.changes += 1 m = self.msg ("SET STATE " + state) return (m) @@ -231,38 +128,9 @@ def set_cur_loc (self, i): """Set current game location.""" - self.changes += 1 m = self.msg ("SET LOC " + str(i)) return (m) - def add_new_loc (self): - """Create a new location.""" - i = self.get_cur_loc () - self.set_cur_loc (-1) - self.set_cur_loc (i) - - def get_loc_player (self, i): - """Get player for the i-th position.""" - m = self.msg ("GET LOC PLAYER " + (str (i))) - return (m) - - def set_loc_player (self, i, player): - """Set player for the i-th position.""" - self.changes += 1 - m = self.msg ("SET LOC PLAYER " + (str (i)) + " " + player) - return (m) - - def get_loc_payoff (self, i, player): - """Get [player]s payoff for the i-th position.""" - m = self.msg ("GET LOC PAYOFF " + (str (i)) + " " + player) - return (m) - - def set_loc_payoff (self, i, player, pay): - """Set [player]s payoff for the i-th position.""" - self.changes += 1 - m = self.msg ("SET LOC PAYOFF " + (str (i)) + " " + player + " " + pay) - return (m) - def get_payoffs (self): """Get (evaluated) payoffs for all players in the current location.""" m = self.msg ("GET PAYOFF") @@ -285,92 +153,6 @@ int (gs[1].strip()))) return ([make_move(m.strip('[] ')) for m in moves]) - def itvls_str (self, itvls): - """Print a list of intervals to string.""" - return (", ".join([f + ": " + str (s) + " -- " + str (e) - for (f,s,e) in itvls])) - - def set_loc_moves (self, i, moves): - """Set moves (3ples (rule, interval, loc)) for the i-th position.""" - moves_str = "; ".join(["[" + r + ", " + iv + " -> " + str(l) + "]" - for (r, iv, l) in moves]) - self.changes += 1 - m = self.msg ("SET LOC MOVES " + (str (i)) + " " + moves_str) - return (m) - - def get_rdata (self, i): - m = self.msg ("GET DATA r" + (str (i))) - if m[0:3] == "ERR": return ("none") - return (m) - - def set_rdata (self, i, data_s): - self.changes += 1 - return (self.msg ("SET DATA r" + (str (i)) + " " + data_s)) - - def set_arity (self, rel, i): - m = self.msg ("SET SIGNATURE " + rel + " " + str(i)) - return (m) - - def add_rule (self): - rule_name = str(len(self.rules) + 1) - self.rule_names.append(rule_name) - emptyr_str = " [||]->[||] with [] pre true inv true post true" - self.changes += 1 - self.msg ("SET RULE " + rule_name + emptyr_str) - rl = ModelClient (self, rule_name, 0) - rr = ModelClient (self, rule_name, 1) - self.rules.append ((rl, rr)) - return (len(self.rules)) - - - def get_conditions (self, i): - m = self.msg ("GET RULE cond " + self.rule_names[i]) - return ([c.strip() for c in m.split(";")]) - - def set_conditions (self, i, pre_s, inv_s, post_s): - self.changes += 1 - m = self.msg ("SET RULE cond " + self.rule_names[i] + " " + pre_s + - " " + inv_s + " " + post_s) - return (m) - - def get_emb_rels (self, i): - m = self.msg ("GET RULE emb " + self.rule_names[i]) - return (m) - - def set_emb_rels (self, i, lst_s): - self.changes += 1 - m = self.msg ("SET RULE emb " + self.rule_names[i] + " " + lst_s) - return (m) - - def get_embeddings (self, i, elem): - m = self.msg ("GET RULE assoc " + self.rule_names[i] + " " + str(elem)) - return (m) - - def set_embeddings (self, i, elem, lst_s): - self.changes += 1 - m = self.msg ("SET RULE assoc " + self.rule_names[i] + " "+ str(elem) + " " + lst_s) - return (m) - - def get_update (self, i, elem, fun): - m = self.msg ("GET RULE update " + self.rule_names[i] + " "+ fun + " " + str(elem)) - return (m) - - def set_update (self, i, elem, fun, t): - self.changes += 1 - m = self.msg ("SET RULE update " + self.rule_names[i] + " " + - fun + " " + str(elem) + " " + t) - return (m) - - def get_dynamic (self, i, elem, fun): - m = self.msg ("GET RULE dynamics "+ self.rule_names[i] +" "+ fun + " " + str(elem)) - return (m) - - def set_dynamic (self, i, elem, fun, t): - self.changes += 1 - m = self.msg ("SET RULE dynamics "+ self.rule_names[i] + " " + - fun + " " + str(elem) + " " + t) - return (m) - def query (self, rule_nm): msg = self.msg ("GET RULE " + rule_nm + " MODEL") if msg.find('->') < 0: return ([]) @@ -395,48 +177,10 @@ shifts[seq[0]][seq[1]] = [float(f) for f in seq[2:]] return (shifts) - def set_time (self, tstep, t): - m = self.msg ("SET dynamics " + repr(tstep) + " " + repr(t)) - return (m) - - def get_time (self): - m = self.msg ("GET dynamics") - t = [s.strip() for s in m.split('/')] - return ((float(t[0]), float(t[1]))) - - def suggest (self, no_iters, loc): - (ts, t) = self.get_time () - # Note that we set max. horizon to 500 here - # syntax variant 1: - # "EVAL LOC MOVES advancement_ratio location TIMEOUT time_in_sec method optional_playout_horizon" - # syntax variant 2: - # "EVAL LOC MOVES [{0: heuristic_player_0_loc_0; 1: heuristic_player_1_loc_0}; {0: heuristic_player_0_loc_1; 1: heuristic_player_1_loc_1}] advancement_ratio location TIMEOUT time_in_sec method optional_playout_horizon" - m = self.msg ("EVAL LOC MOVES 2.5 " + str(loc) +" TIMEOUT 120 "+ str(no_iters) + " uct_greedy_playouts 500") - self.set_time (ts, t) - msg = [s.strip() for s in m.split(';')] - emb = dict() - for s in msg[1].split(','): - es = [x.strip() for x in s.split(':')] - emb[es[0]] = es[1] - params = dict() - for s in msg[2].split(','): - ps = [x.strip() for x in s.split(':')] - params[ps[0]] = float(ps[1]) - return ((msg[0], emb, params, int(msg[3]))) - def open_from_str (self, s): state_str = ("#db#") + "$".join (s.split ("\n")) self.set_state (state_str) - def open (self, file_name_s): - file_name = str(file_name_s) - if file_name == '': return - file = open (file_name, 'r') - state = file.read () - file.close () - state_str = ("#"+file_name+"#") + "$".join (state.split ("\n")) - self.set_state (state_str) - def cur_moves (self): cur_loc = self.get_cur_loc () moves = [] @@ -446,15 +190,6 @@ moves.append ((m, r, endp)) return ("; ".join([str(m) for m in moves])) - def cur_move_touching (self, elem): - cur_loc = self.get_cur_loc () - moves = [] - for (r, itvls, endp) in self.get_loc_moves (cur_loc): - for m in self.query (r): - # FIXME! currently we ignore params in html (skip itvls here) - if str(elem) in m.values(): moves.append ((m, r, endp)) - return ("; ".join([str(m) for m in moves])) - def make_move (self, m, r, endp): self.apply_rule (r, m, 1.0, []) self.set_cur_loc (endp) Modified: trunk/Toss/WebClient/make_db.py =================================================================== --- trunk/Toss/WebClient/make_db.py 2010-12-15 00:02:30 UTC (rev 1251) +++ trunk/Toss/WebClient/make_db.py 2010-12-16 22:53:03 UTC (rev 1252) @@ -3,16 +3,22 @@ import os from pysqlite2 import dbapi2 as sqlite3 +TUID = "toss_id_05174_" # from TossHandler import TUID + print "Creating empty Toss DB" conn = sqlite3.connect("tossdb.sqlite") conn.execute("create table passwd(id string primary key, passwd string)") -conn.execute("create table cur_states(playid int primary key, game string, player1 string, player2 string, move int, toss string, svg string)") -conn.execute("create table old_states(playid int, game string, player1 string, player2 string, move int, toss string, svg string)") +conn.execute("create table cur_states(playid int primary key, game string, player1 string, player2 string, move int, toss string, info string, svg string)") +conn.execute("create table old_states(playid int, game string, player1 string, player2 string, move int, toss string, info string, svg string)") conn.execute("create table games(game string primary key, toss string)") conn.execute("create table ports(port int primary key, locked bool)") +conn.execute("create table lock(tid int primary key, locked bool)") conn.commit () +conn.execute ("insert into lock(tid, locked) values (?, ?)", + (TUID, 'false')) + def add_game (g): f = open("../examples/" + g + ".toss") toss = f.read() Modified: trunk/Toss/WebClient/register.html =================================================================== --- trunk/Toss/WebClient/register.html 2010-12-15 00:02:30 UTC (rev 1251) +++ trunk/Toss/WebClient/register.html 2010-12-16 22:53:03 UTC (rev 1252) @@ -33,7 +33,8 @@ function register () { un = document.getElementById('username').value; pwd = document.getElementById('password').value; - sync_server_msg ("REGISTER#" + un + " " + crypt(pwd)); + ts = "toss##in$$some167S4lT_-"; + sync_server_msg ("REGISTER#" + un + " " + crypt(ts + pwd)); } </script> </body> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-15 00:02:37
|
Revision: 1251 http://toss.svn.sourceforge.net/toss/?rev=1251&view=rev Author: lukaszkaiser Date: 2010-12-15 00:02:30 +0000 (Wed, 15 Dec 2010) Log Message: ----------- Grouping toss requests and separating commands. WebClient works in multi-client mode except for small problems mentioned in comments in TossHandler. Modified Paths: -------------- trunk/Toss/WebClient/TossConnect.js trunk/Toss/WebClient/TossHandler.py trunk/Toss/WebClient/TossMain.js trunk/Toss/WebClient/TossStyle.css Modified: trunk/Toss/WebClient/TossConnect.js =================================================================== --- trunk/Toss/WebClient/TossConnect.js 2010-12-14 00:28:32 UTC (rev 1250) +++ trunk/Toss/WebClient/TossConnect.js 2010-12-15 00:02:30 UTC (rev 1251) @@ -12,7 +12,6 @@ var SVG_HEIGHT = 500; var SVG_MARGINX = 50; var SVG_MARGINY = 50; -var TOSS_PORT = 0; var VIEW_WIDTH = "19em"; var VIEW_HEIGHT = "19em"; var VIEW_MIRROR = 0; @@ -26,6 +25,12 @@ var CACHED_MOVES = "" +var DIM_STR = "" +var ELEM_STR = "" +var RELS_STR = "" +var MOVES_STR = "" + + // Helper function: sign of a number. function sign (x) { if (x > 0.01) { return (1); } @@ -38,6 +43,17 @@ CACHED_MOVES = ""; } +function set_info (info) { + var res_arr = []; + res_arr = info.split("$"); + if (res_arr.length != 4) { return (false); } + DIM_STR = res_arr[0]; + ELEM_STR = res_arr[1]; + RELS_STR = res_arr[2]; + MOVES_STR = res_arr[3]; + return (true); +} + // Send [msg] to server and return response text. function sync_server_msg (msg) { var xml_request = new XMLHttpRequest (); @@ -60,9 +76,9 @@ return (d.replace(" ", "$")); } -// Send [msg] to server attaching prefix '[port]#' and return response text. -function srv (port, msg) { - return (sync_server_msg (port.toString() + '#' + msg)); +// Send [msg] to server attaching prefix '[cmd]#' and return response text. +function srv (cmd, msg) { + return (sync_server_msg (cmd + '#' + msg)); } // Strip [c1] and [c2] from beginning and end of [str]. @@ -91,15 +107,11 @@ return (res_arr); } -// Get elements of Toss Model active on [port]. -function get_elems (port) { - return (convert_python_list (',', srv(port, "c.model.get_elems()"))); -} -// Get moves applicable to [elem] in Toss Model active on [port]. -function get_moves (port, elem) { +// Get moves applicable to [elem] in a game. +function get_moves (elem) { if (CACHED_MOVES == "") { - CACHED_MOVES = srv (port, 'c.cur_moves()'); + CACHED_MOVES = MOVES_STR } var all_moves = convert_python_list (';', CACHED_MOVES); var elem_moves = [] @@ -111,9 +123,9 @@ return (elem_moves) } -// Get relation tuples of Toss Model active on [port]. -function get_rels (port) { - var r = convert_python_list(';', srv (port, "c.model.get_rels_simple ()")); +// Get relation tuples. +function get_rels () { + var r = convert_python_list(';', RELS_STR); var rels = []; for (var i = 0; i < r.length; i++) { var rel_name = strip(' ', '\'', r[i].substring(1,r[i].indexOf(','))); @@ -136,17 +148,9 @@ return ([x + SVG_MARGINX, y + SVG_MARGINY]) } -// Get position of element [elem] from Toss Model active on [port]. -function get_elem_pos (port, elem) { - res = srv(port, 'c.model.get_elem_pos("' + elem + '")'); - res_pair = strip('(', ')', res).split(','); - return (translate_pos ([parseFloat(strip(' ', ' ', res_pair[0])), - parseFloat(strip(' ', ' ', res_pair[1]))])) -} - -// Get elements and positions of Toss Model active on [port]. -function get_elems_with_pos (port) { - var l = convert_python_list(',', srv(port, "c.model.get_elems_with_pos()")); +// Get elements and positions. +function get_elems_with_pos () { + var l = convert_python_list(',', ELEM_STR); ELEMS = []; ELEM_POS = {}; for (var i = 0; i < l.length; i++) { @@ -157,18 +161,11 @@ } -// Open Toss Server, set TOSS_PORT to the port on which it is opened. -function open_toss_server () { - if (TOSS_PORT > 0) { return; } - var port = sync_server_msg ("OPEN TOSS"); - TOSS_PORT = port; -} - -// Open [file_name] on Toss Server running on port [port] and get dimenstions. +// Open [file_name] on Toss Server and get info. function toss_open_game (game_name) { - open_toss_server (); - srv (TOSS_PORT, 'open_game(c, "' + game_name + '")'); - var dim_msg = srv (TOSS_PORT, "c.model.get_dim()"); + var info = srv ("OPENGAME", game_name); + set_info (info); + var dim_msg = DIM_STR; var dim = strip('(', ')', dim_msg).split(','); MODEL_MAXX = parseFloat(strip(' ', ' ', dim[0])); MODEL_MINX = parseFloat(strip(' ', ' ', dim[1])); @@ -178,11 +175,11 @@ MODEL_HEIGHT = Math.max (SVG_HEIGHT / 100, (MODEL_MAXY - MODEL_MINY)); } -// Open [file_name] on Toss Server running on port [port] and get dimenstions. +// Open [file_name] on Toss Server and get info. function toss_open_db (file_name_params) { - open_toss_server (); - srv (TOSS_PORT, 'open_db(c, ' + file_name_params + ')'); - var dim_msg = srv (TOSS_PORT, "c.model.get_dim()"); + var info = srv ("OPEN_DB", 'c, ' + file_name_params); + set_info (info); + var dim_msg = DIM_STR; var dim = strip('(', ')', dim_msg).split(','); MODEL_MAXX = parseFloat(strip(' ', ' ', dim[0])); MODEL_MINX = parseFloat(strip(' ', ' ', dim[1])); Modified: trunk/Toss/WebClient/TossHandler.py =================================================================== --- trunk/Toss/WebClient/TossHandler.py 2010-12-14 00:28:32 UTC (rev 1250) +++ trunk/Toss/WebClient/TossHandler.py 2010-12-15 00:02:30 UTC (rev 1251) @@ -46,10 +46,11 @@ def get_toss_port (): free_ports = get_all_from_db ("ports", "locked='false'") if len(free_ports) == 0: - fid = 0 + fid = 0 for f in db.execute ("select count(*) from ports"): fid = int(f[0]) port = 8110+fid+1 + # WARNING: two proc can get same fid! Avoid by sqlite write-atomicity! db.execute ("insert into ports(port, locked) values (?, ?)", (port, 'true')) db.commit () @@ -57,6 +58,7 @@ return (port) (port, _) = free_ports[0] db.execute ("update ports set locked='true' where port=" + str(port)) + # This could give same port to 2 proc (1st line). Avoid by sql-write! db.commit () return (port) @@ -94,27 +96,44 @@ return("game='" + g + "' and player1='" + p1 + "' and player2='" + p2 + "' and playid=" + pid + " and move=" + m) +def get_game_info (client): + dim_s = str(client.model.get_dim()) + model_s = str(client.model.get_elems_with_pos()) + rels_s = str(client.model.get_rels_simple()) + moves_s = str(client.cur_moves()) + return (dim_s + "$" + model_s + "$" + rels_s + "$" + moves_s) + def open_db (client, game, p1, p2, pid, move): select_s = game_select_s (game, p1, p2, pid, move) res = get_all_from_db ("cur_states", select_s) (_, _, _, _, _, toss, _) = res[0] client.open_from_str (toss) + return (get_game_info (client)) def open_game (client, game): res = get_all_from_db ("games", "game='" + game + "'") (_, toss) = res[0] client.open_from_str (toss) + return (get_game_info (client)) -def move_play (client, g, p1, p2, pid, m, svg_s): +def move_play (client, move_tup, g, p1, p2, pid, m): + open_db (client, g, p1, p2, pid, m) + (move1, move2, move3) = move_tup + client.make_move (move1, move2, move3) new_toss = client.get_state () select_s = game_select_s (g, p1, p2, pid, m) old_res = get_all_from_db ("cur_states", select_s) (_, _, _, _, _, old_toss, old_svg) = old_res[0] db.execute ("delete from cur_states where " + select_s) db_old_insert (g, p1, p2, pid, m, old_toss, old_svg) - db_cur_insert (g, p1, p2, pid, int(m) + 1, new_toss, svg_s) - return ("OK") + db_cur_insert (g, p1, p2, pid, int(m) + 1, new_toss, "") + return (get_game_info (client)) +def upd_svg (g, p1, p2, pid, m, svg_s): + select_s = game_select_s (g, p1, p2, pid, m) + db.execute ("update cur_states set svg='" + svg_s + "' where " + select_s) + db.commit () + def passwd_from_db (uid): res = get_all_from_db ("passwd", "id='" + uid + "'") if len(res) > 1: raise Exception ("db", "multiple passwords for " + uid) @@ -162,9 +181,6 @@ usr = confirm_username (req) msg = req.read () #tmp_log(msg) - if msg.find('#') == -1: - req.write(str(17)) # not used any more - return apache.OK cmd, sep, data = msg.partition('#') if cmd == "USERNAME": req.write(usr) @@ -190,16 +206,27 @@ Cookie.add_cookie(req, cookie) req.write ("user logged out: " + usr + ".") return apache.OK - if cmd == "LISTPLAYS": - res = eval(data) + if cmd == "LIST_PLAYS": + res = eval (cmd.lower() + "(" + data + ")") req.write(str(res)) return apache.OK if cmd == "FREEID": req.write(str(get_free_id ())) return apache.OK - port = get_toss_port () - c = SystemClient ("localhost", port) - res = eval (data) - release_toss_port (port) - req.write(str(res)) + if cmd == "OPENGAME": + port = get_toss_port () + c = SystemClient ("localhost", port) + res = open_game(c, data) + release_toss_port (port) + req.write(str(res)) + return apache.OK + if ((cmd == "OPEN_DB") or (cmd == "UPD_SVG") or + (cmd == "NEW_PLAY") or (cmd == "MOVE_PLAY")): + port = get_toss_port () + c = SystemClient ("localhost", port) + res = eval (cmd.lower() + "(" + data + ")") + release_toss_port (port) + req.write(str(res)) + return apache.OK + req.write("MOD_PYTHON ERROR ; Traceback: Unknown Toss Command! \n " + cmd) return apache.OK Modified: trunk/Toss/WebClient/TossMain.js =================================================================== --- trunk/Toss/WebClient/TossMain.js 2010-12-14 00:28:32 UTC (rev 1250) +++ trunk/Toss/WebClient/TossMain.js 2010-12-15 00:02:30 UTC (rev 1251) @@ -15,12 +15,11 @@ // Get model information from server. function get_model_info () { - get_elems_with_pos (TOSS_PORT); + get_elems_with_pos (); for (var i = 0; i < ELEMS.length; i++) { ELEM_COUNTERS[ELEMS[i]] = 0; - //ELEM_POS[ELEMS[i]] = get_elem_pos (TOSS_PORT, ELEMS[i]); } - RELS = get_rels (TOSS_PORT); + RELS = get_rels (); var sqrt = Math.round (Math.sqrt (ELEMS.length)); if (sqrt * sqrt == ELEMS.length) { // perhaps a grid SUGGESTED_ELEM_SIZEX = SVG_WIDTH / (2.0 * (sqrt-1)); @@ -100,7 +99,7 @@ // Handler for clicks on elements. function handle_elem_click (elem) { - var moves = get_moves (TOSS_PORT, elem); + var moves = get_moves (elem); if (moves.length > ELEM_COUNTERS[elem]) { show_move (moves[ELEM_COUNTERS[elem]]); ELEM_COUNTERS[elem] += 1; @@ -110,7 +109,7 @@ } } -function play_file_cmd (i) { +function play_py_id (i) { return ("'" + GAME_NAME + "', '" + PLAYS[i][0] + "', '" + PLAYS[i][1] + "', '" + PLAYS[i][2] + "', '" + PLAYS[i][3] + "'") } @@ -129,7 +128,7 @@ } function list_plays (game) { - var lst = srv ("LISTPLAYS", "list_plays ('" + game + "', '" + UNAME + "')"); + var lst = srv ("LIST_PLAYS", "'" + game + "', '" + UNAME + "'"); PLAYS = convert_python_list (',', lst); var plist = document.getElementById("plays-list-" + game); while (plist.childNodes.length > 0) { plist.removeChild(plist.firstChild); } @@ -172,7 +171,7 @@ VIEW_MIRROR = (PLAYS[CUR_PLAY_I][0] == UNAME) ? 0 : 1; document.getElementById("cur-player").innerHTML = PLAYS[CUR_PLAY_I][PLAYS[CUR_PLAY_I][3] % 2]; - toss_open_db (play_file_cmd(pi)); + toss_open_db (play_py_id(pi)); full_redraw (); } @@ -185,7 +184,8 @@ alert ("It is your Opponent's turn"); return; } - srv (TOSS_PORT, 'c.make_move' + CUR_MOVE); + var info = srv("MOVE_PLAY", 'c, '+ CUR_MOVE +', '+ play_py_id (CUR_PLAY_I)); + set_info (info); clear_move_cache (); CUR_MOVE = ""; CUR_ELEMS = []; @@ -194,9 +194,8 @@ PLAYS[CUR_PLAY_I][(m + 1) % 2]; document.getElementById('cur-move').innerHTML = "none"; full_redraw (); - var fn = play_file_cmd (CUR_PLAY_I); PLAYS[CUR_PLAY_I][3] = parseInt(PLAYS[CUR_PLAY_I][3]) + 1; - srv (TOSS_PORT, "move_play(c, " + fn + ", " + svg_string () + ")"); + srv ("UPD_SVG", play_py_id(CUR_PLAY_I) + ", " + svg_string()); var old_li = document.getElementById ("plays-list-" + GAME_NAME + "-elem-" + CUR_PLAY_I); var li = new_play_item (GAME_NAME, CUR_PLAY_I); old_li.parentNode.replaceChild (li, old_li); @@ -315,8 +314,8 @@ PLAYS.push(p); toss_open_game (GAME_NAME); full_redraw (); - var fn = play_file_cmd (CUR_PLAY_I); - srv (TOSS_PORT, "new_play(" + fn + ", " + svg_string () + ")"); + var fn = play_py_id (CUR_PLAY_I); + srv ("NEW_PLAY", fn + ", " + svg_string ()); li = new_play_item (GAME_NAME, CUR_PLAY_I); document.getElementById("plays-list-" + GAME_NAME).appendChild(li); } Modified: trunk/Toss/WebClient/TossStyle.css =================================================================== --- trunk/Toss/WebClient/TossStyle.css 2010-12-14 00:28:32 UTC (rev 1250) +++ trunk/Toss/WebClient/TossStyle.css 2010-12-15 00:02:30 UTC (rev 1251) @@ -367,10 +367,10 @@ .chessW .chess-path-A { opacity:1; - fill:#ffffff; + fill:#ffe4aa; fill-opacity:1; fill-rule:nonzero; - stroke:#000000; + stroke:#260314; stroke-width:1.5; stroke-linecap:round; stroke-linejoin:miter; @@ -382,10 +382,10 @@ .chessB .chess-path-A { opacity:1; - fill:#000000; + fill:#400827; fill-opacity:1; fill-rule:nonzero; - stroke:#000000; + stroke:#260314; stroke-width:1.5; stroke-linecap:round; stroke-linejoin:miter; @@ -397,10 +397,10 @@ .chessW .chess-path-B { opacity:1; - fill:#ffffff; + fill:#ffe4aa; fill-opacity:1; fill-rule:evenodd; - stroke:#000000; + stroke:#260314; stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round; @@ -411,10 +411,10 @@ .chessB .chess-path-B { opacity:1; - fill:#000000; + fill:#400827; fill-opacity:1; fill-rule:evenodd; - stroke:#000000; + stroke:#260314; stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round; @@ -425,9 +425,9 @@ .chessW .chess-path-C { opacity:1; - fill:#000000; + fill:#400827; fill-opacity:1; - stroke:#000000; + stroke:#260314; stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round; @@ -438,9 +438,9 @@ .chessB .chess-path-C { opacity:1; - fill:#ffffff; + fill:#ffe4aa; fill-opacity:1; - stroke:#ffffff; + stroke:#ffe4aa; stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round; @@ -450,10 +450,10 @@ } .chessW .chess-path-D { - fill: #ffffff; + fill: #ffe4aa; fill-opacity: 0.75; fill-rule:evenodd; - stroke: #000000; + stroke: #260314; stroke-width:1; stroke-linecap:round; stroke-linejoin:mitter; @@ -463,10 +463,10 @@ } .chessB .chess-path-D { - fill: #000000; + fill: #400827; fill-opacity: 0.75; fill-rule:evenodd; - stroke: #000000; + stroke: #ffe4aa; stroke-width:1; stroke-linecap:round; stroke-linejoin:mitter; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-14 00:28:39
|
Revision: 1250 http://toss.svn.sourceforge.net/toss/?rev=1250&view=rev Author: lukaszkaiser Date: 2010-12-14 00:28:32 +0000 (Tue, 14 Dec 2010) Log Message: ----------- Moving WebClient to internal toss port handling. This requires that toss state (or its db id) is communicated at each request which is not the case now - the current version will break in multi-user case (to be corrected soon). Modified Paths: -------------- trunk/Toss/WebClient/TossHandler.py trunk/Toss/WebClient/make_db.py Modified: trunk/Toss/WebClient/TossHandler.py =================================================================== --- trunk/Toss/WebClient/TossHandler.py 2010-12-12 23:31:07 UTC (rev 1249) +++ trunk/Toss/WebClient/TossHandler.py 2010-12-14 00:28:32 UTC (rev 1250) @@ -36,10 +36,6 @@ except: return (False) -def free_toss_port (): - for i in range(10000): - if not (is_toss_server ("localhost", 8110 + i)): return (8110 + i) - def open_toss_server (port): args = ["/var/www/WebClient/TossServer", "-s", "localhost", "-t", "600", "-p", str(port)] @@ -47,6 +43,27 @@ time.sleep (0.1) return (port) +def get_toss_port (): + free_ports = get_all_from_db ("ports", "locked='false'") + if len(free_ports) == 0: + fid = 0 + for f in db.execute ("select count(*) from ports"): + fid = int(f[0]) + port = 8110+fid+1 + db.execute ("insert into ports(port, locked) values (?, ?)", + (port, 'true')) + db.commit () + open_toss_server (port) + return (port) + (port, _) = free_ports[0] + db.execute ("update ports set locked='true' where port=" + str(port)) + db.commit () + return (port) + +def release_toss_port (port): + db.execute ("update ports set locked='false' where port=" + str(port)) + db.commit () + def cp (f1, f2): subprocess.call(["cp", f1, f2]) @@ -54,17 +71,17 @@ or_s = "(player1='" + player_id + "' or player2='" + player_id + "')" plays = get_all_from_db ("cur_states", "game='" + game + "' and " + or_s) def play_name (p): - (g, p1, p2, pid, move, toss, svg) = p + (pid, g, p1, p2, move, toss, svg) = p return ("/plays/" + str(g) + "_" + str(p1) + "_" + str(p2) + "_" + str(pid) + "_" + str(move)) return (str([play_name (p) for p in plays])) def db_cur_insert (game, p1, p2, pid, move, toss, svg_str): - db.execute ("insert into cur_states(game, player1, player2, playid, move, toss, svg) values (?, ?, ?, ?, ?, ?, ?)", (game, p1, p2, pid, move, toss, svg_str)) + db.execute ("insert into cur_states(playid, game, player1, player2, move, toss, svg) values (?, ?, ?, ?, ?, ?, ?)", (pid, game, p1, p2, move, toss, svg_str)) db.commit () def db_old_insert (game, p1, p2, pid, move, toss, svg_str): - db.execute ("insert into old_states(game, player1, player2, playid, move, toss, svg) values (?, ?, ?, ?, ?, ?, ?)", (game, p1, p2, pid, move, toss, svg_str)) + db.execute ("insert into old_states(playid, game, player1, player2, move, toss, svg) values (?, ?, ?, ?, ?, ?, ?)", (pid, game, p1, p2, move, toss, svg_str)) db.commit () def new_play (game, p1, p2, pid, move, svg_str): @@ -146,8 +163,7 @@ msg = req.read () #tmp_log(msg) if msg.find('#') == -1: - port = open_toss_server (free_toss_port ()) - req.write(str(port)) + req.write(str(17)) # not used any more return apache.OK cmd, sep, data = msg.partition('#') if cmd == "USERNAME": @@ -181,7 +197,9 @@ if cmd == "FREEID": req.write(str(get_free_id ())) return apache.OK - c = SystemClient ("localhost", int(cmd)) + port = get_toss_port () + c = SystemClient ("localhost", port) res = eval (data) + release_toss_port (port) req.write(str(res)) return apache.OK Modified: trunk/Toss/WebClient/make_db.py =================================================================== --- trunk/Toss/WebClient/make_db.py 2010-12-12 23:31:07 UTC (rev 1249) +++ trunk/Toss/WebClient/make_db.py 2010-12-14 00:28:32 UTC (rev 1250) @@ -7,9 +7,10 @@ conn = sqlite3.connect("tossdb.sqlite") conn.execute("create table passwd(id string primary key, passwd string)") -conn.execute("create table cur_states(game string, player1 string, player2 string, playid int, move int, toss string, svg string)") -conn.execute("create table old_states(game string, player1 string, player2 string, playid int, move int, toss string, svg string)") +conn.execute("create table cur_states(playid int primary key, game string, player1 string, player2 string, move int, toss string, svg string)") +conn.execute("create table old_states(playid int, game string, player1 string, player2 string, move int, toss string, svg string)") conn.execute("create table games(game string primary key, toss string)") +conn.execute("create table ports(port int primary key, locked bool)") conn.commit () def add_game (g): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2010-12-12 23:31:14
|
Revision: 1249 http://toss.svn.sourceforge.net/toss/?rev=1249&view=rev Author: lukaszkaiser Date: 2010-12-12 23:31:07 +0000 (Sun, 12 Dec 2010) Log Message: ----------- Move play listing to the main page. Modified Paths: -------------- trunk/Toss/WebClient/README trunk/Toss/WebClient/TossConnect.js trunk/Toss/WebClient/TossHandler.py trunk/Toss/WebClient/TossMain.js trunk/Toss/WebClient/TossStyle.css trunk/Toss/WebClient/index.html Modified: trunk/Toss/WebClient/README =================================================================== --- trunk/Toss/WebClient/README 2010-12-12 20:24:21 UTC (rev 1248) +++ trunk/Toss/WebClient/README 2010-12-12 23:31:07 UTC (rev 1249) @@ -19,8 +19,7 @@ TODO: - - bug with play numbering with different players (or just hide numbers?) - - change wording from play to game + - redo TossServer calls and caching - enable google (or other) analytics - refresh (async?) plays in which the other player moves - move interface: first click all, second click toggle, if one - confirm msg Modified: trunk/Toss/WebClient/TossConnect.js =================================================================== --- trunk/Toss/WebClient/TossConnect.js 2010-12-12 20:24:21 UTC (rev 1248) +++ trunk/Toss/WebClient/TossConnect.js 2010-12-12 23:31:07 UTC (rev 1249) @@ -60,26 +60,6 @@ return (d.replace(" ", "$")); } -// Login -function login () { - un = document.getElementById('username').value; - pwd = document.getElementById('password').value; - resp = sync_server_msg ("LOGIN#" + un + " " + crypt(pwd)); - if (resp == "OK") { - UNAME = un; - document.getElementById("topuser").innerHTML = "Welcome " + un; - document.getElementById("loginform").style.display = "none"; - } else { - alert (resp) - } -} - -// Logout -function logout () { - document.getElementById("loginform").style.display = "inline"; - document.getElementById("topuser").innerHTML = ""; -} - // Send [msg] to server attaching prefix '[port]#' and return response text. function srv (port, msg) { return (sync_server_msg (port.toString() + '#' + msg)); Modified: trunk/Toss/WebClient/TossHandler.py =================================================================== --- trunk/Toss/WebClient/TossHandler.py 2010-12-12 20:24:21 UTC (rev 1248) +++ trunk/Toss/WebClient/TossHandler.py 2010-12-12 23:31:07 UTC (rev 1249) @@ -119,9 +119,10 @@ db_pwd = passwd_from_db (uid) if not db_pwd: return ("no such user registered") if (pwd != db_pwd): return ("wrong password") - cookie1 = Cookie.Cookie(TUID + 'username', uid) - cookie2 = Cookie.Cookie(TUID + 'passphrase', pwd) - Cookie.add_cookie(req, cookie1) + t = time.time() + 3600; + cookie1 = Cookie.Cookie(TUID + 'username', uid, expires=t) + cookie2 = Cookie.Cookie(TUID + 'passphrase', pwd, expires=t) + Cookie.add_cookie(req, cookie1) Cookie.add_cookie(req, cookie2) return ("OK") @@ -131,6 +132,12 @@ db.commit () return (True) +def get_free_id (): + fid = 0 + for f in db.execute ("select count(*) from cur_states"): + fid = int(f[0]) + return (fid + 1) + def handler(req): global db req.content_type = "text/plain" @@ -162,10 +169,18 @@ req.write("Login failed for " + uname + ": " + res) return apache.OK if cmd == "LOGOUT": - cookie = Cookie.Cookie(TUID + 'passphrase', "") + cookie = Cookie.Cookie(TUID + 'passphrase', "a") + cookie = Cookie.Cookie(TUID + 'username', "a") Cookie.add_cookie(req, cookie) req.write ("user logged out: " + usr + ".") return apache.OK + if cmd == "LISTPLAYS": + res = eval(data) + req.write(str(res)) + return apache.OK + if cmd == "FREEID": + req.write(str(get_free_id ())) + return apache.OK c = SystemClient ("localhost", int(cmd)) res = eval (data) req.write(str(res)) Modified: trunk/Toss/WebClient/TossMain.js =================================================================== --- trunk/Toss/WebClient/TossMain.js 2010-12-12 20:24:21 UTC (rev 1248) +++ trunk/Toss/WebClient/TossMain.js 2010-12-12 23:31:07 UTC (rev 1249) @@ -6,7 +6,6 @@ var PLAYS = []; var CUR_PLAY_I = -1; -var MAX_PLAY_NO = 0; var FRIENDS = [] @@ -111,69 +110,47 @@ } } -function play_file_name (i) { - return ("/plays/" + GAME_NAME + "_" + PLAYS[i][0] + "_" + - PLAYS[i][1] + "_" + PLAYS[i][2] + "_" + PLAYS[i][3]) -} - function play_file_cmd (i) { return ("'" + GAME_NAME + "', '" + PLAYS[i][0] + "', '" + PLAYS[i][1] + "', '" + PLAYS[i][2] + "', '" + PLAYS[i][3] + "'") } -function new_play_item (i) { +function new_play_item (game, i) { var li = document.createElement('li'); li.setAttribute ("class", "plays-list-elem"); - li.setAttribute ("id", "plays-list-elem-" + i); - var fn = play_file_name (i); + li.setAttribute ("id", "plays-list-" + game + "-elem-" + i); var p = PLAYS[i][2]; li.innerHTML = "" + PLAYS[i][2] + ': ' + PLAYS[i][0] + " vs " + PLAYS[i][1] + " " + //" move " + PLAYS[i][3] + " "+ - '<a title="Open" href="#" onclick="'+ "play_click('"+ fn + "', " + p + - ", " + i + ')"><img title="Open" height="20" width="20" class="thumb"'+ - ' src="' + fn + '.png" alt="Play '+ PLAYS[i][2] + '"/></a>'; - // '<a href="#" onclick="'+ "play_click('"+ fn + "', " + p + ", " + i + - // ')">Open</a>'; + '<a title="Open" href="#" onclick="'+ "play_click('"+ game + "', " + p + + ", " + i + ')">Open</a>'; // +'<a href="#" onclick="'+ "del_play('"+ fn + "')" + '">Delete</a>'; return (li); } function list_plays (game) { - MAX_PLAY_NO = 0; - var lst = srv (TOSS_PORT, "list_plays ('" + game + "', '" + UNAME + "')"); - PLAYS = convert_python_list ('\n', strip ('\n', ' ', lst)); - var plist = document.getElementById("plays-list"); + var lst = srv ("LISTPLAYS", "list_plays ('" + game + "', '" + UNAME + "')"); + PLAYS = convert_python_list (',', lst); + var plist = document.getElementById("plays-list-" + game); while (plist.childNodes.length > 0) { plist.removeChild(plist.firstChild); } var d = game.length + 2; for (var i = 0; i < PLAYS.length; i++) { var p = PLAYS[i].substring(PLAYS[i].lastIndexOf('/') + d); PLAYS[i] = convert_python_list ('_', p); - if (PLAYS[i][2] > MAX_PLAY_NO) { MAX_PLAY_NO = PLAYS[i][2]; } - plist.appendChild(new_play_item (i)); + plist.appendChild(new_play_item (game, i)); } if (PLAYS.length == 0) { - document.getElementById("plays-txt").style.display = "none"; - document.getElementById("plays-list").style.display = "none"; + document.getElementById("plays-list-" + game).style.display = "none"; } else { - document.getElementById("plays-txt").style.display = "block"; - document.getElementById("plays-list").style.display = "block"; + document.getElementById("plays-list-" + game).style.display = "block"; } } function game_click (game) { document.getElementById("welcome").style.display = "none"; - document.getElementById("board-disp").style.display = "none"; document.getElementById("game-disp").style.display = "none"; - document.getElementById("game-desc").style.display = "block"; - if (GAME_NAME != "") { - document.getElementById(GAME_NAME).className = ""; - document.getElementById(GAME_NAME + "-desc").style.display = "none"; - clear_svg (); - } - document.getElementById ("game-title").innerHTML = game; - document.getElementById(game).className = "game-highlighted"; + document.getElementById("plays").style.display = "none"; GAME_NAME = game; - document.getElementById(GAME_NAME + "-desc").style.display = "block"; if (game == "Tic-Tac-Toe") { // bigger margins needed create_svg_box ("19em", "19em", 130, 130, "board"); } else { @@ -182,13 +159,14 @@ document.getElementById("opening").style.display = "block"; toss_open_game (game); document.getElementById("opening").style.display = "none"; - list_plays (game); document.getElementById("game-disp").style.display = "block"; } -function play_click (play, play_id, pi) { - document.getElementById("game-desc").style.display = "none"; - document.getElementById("board-disp").style.display = "block"; +function play_click (game, play_id, pi) { + list_plays (game) + game_click (game) + document.getElementById ("game-title").innerHTML = game; + document.getElementById("game-disp").style.display = "block"; document.getElementById("play-number").innerHTML = "" + play_id; CUR_PLAY_I = pi; VIEW_MIRROR = (PLAYS[CUR_PLAY_I][0] == UNAME) ? 0 : 1; @@ -219,8 +197,8 @@ var fn = play_file_cmd (CUR_PLAY_I); PLAYS[CUR_PLAY_I][3] = parseInt(PLAYS[CUR_PLAY_I][3]) + 1; srv (TOSS_PORT, "move_play(c, " + fn + ", " + svg_string () + ")"); - var old_li = document.getElementById ("plays-list-elem-" + CUR_PLAY_I); - var li = new_play_item (CUR_PLAY_I); + var old_li = document.getElementById ("plays-list-" + GAME_NAME + "-elem-" + CUR_PLAY_I); + var li = new_play_item (GAME_NAME, CUR_PLAY_I); old_li.parentNode.replaceChild (li, old_li); } @@ -272,9 +250,10 @@ document.getElementById("opponents").style.display = "block"; } -function new_play () { - if (UNAME == "") { alert ("Please log in to create plays"); return; } - make_opnt_list (); +function new_play (game) { + if (UNAME == "") { alert ("Please log in to create plays"); return; } + GAME_NAME = game; + make_opnt_list (); } function opponents_next () { @@ -317,40 +296,71 @@ } function new_play_do (opp_uid) { + list_plays (GAME_NAME) + game_click (GAME_NAME) document.getElementById("opponents").style.display = "none"; var olist = document.getElementById("opponents-list"); while (olist.childNodes.length > 0) { olist.removeChild(olist.firstChild); } if (opp_uid == -1) { opp_uid = UNAME; } if (opp_uid == 0 || UNAME == "") { return; } - document.getElementById("plays-txt").style.display = "block"; - document.getElementById("plays-list").style.display = "block"; - MAX_PLAY_NO = parseInt(MAX_PLAY_NO) + 1; - document.getElementById("play-number").innerHTML = "" + MAX_PLAY_NO; + document.getElementById("plays-list-" + GAME_NAME).style.display = "block"; + FREE_PLAY_NO = parseInt(srv("FREEID", "play")) + document.getElementById("play-number").innerHTML = "" + FREE_PLAY_NO; CUR_PLAY_I = PLAYS.length; VIEW_MIRROR = 0; document.getElementById("cur-player").innerHTML = UNAME; - document.getElementById("board-disp").style.display = "block"; + document.getElementById("game-disp").style.display = "block"; document.getElementById("plays").style.left = "30em"; - var p = [UNAME, opp_uid, MAX_PLAY_NO, 0]; + var p = [UNAME, opp_uid, FREE_PLAY_NO, 0]; PLAYS.push(p); toss_open_game (GAME_NAME); - document.getElementById("game-desc").style.display = "none"; full_redraw (); var fn = play_file_cmd (CUR_PLAY_I); srv (TOSS_PORT, "new_play(" + fn + ", " + svg_string () + ")"); - li = new_play_item (CUR_PLAY_I); - document.getElementById("plays-list").appendChild(li); + li = new_play_item (GAME_NAME, CUR_PLAY_I); + document.getElementById("plays-list-" + GAME_NAME).appendChild(li); } +function setup_user (un) { + UNAME = un + document.getElementById("topuser").innerHTML = "Welcome " + un; + document.getElementById("loginform").style.display = "none"; + document.getElementById("welcome").style.display = "none"; + document.getElementById("plays").style.display = "block"; + list_plays ("Breakthrough"); + list_plays ("Chess"); + list_plays ("Entanglement"); + list_plays ("Gomoku"); + list_plays ("Tic-Tac-Toe"); +} + function startup () { if (navigator.userAgent.indexOf('MSIE') !=-1) { document.getElementById("nosvg").style.display = "block"; } else { var un = srv("USERNAME", "user"); - if (un != "") { - UNAME = un - document.getElementById("topuser").innerHTML = "Welcome " + un; - document.getElementById("loginform").style.display = "none"; - } + if (un != "") { setup_user (un) }; } } + +// Login +function login () { + un = document.getElementById('username').value; + pwd = document.getElementById('password').value; + resp = sync_server_msg ("LOGIN#" + un + " " + crypt(pwd)); + if (resp == "OK") { + setup_user (un) + } else { + alert (resp) + } +} + +// Logout +function logout () { + document.getElementById("loginform").style.display = "inline"; + document.getElementById("topuser").innerHTML = ""; + document.getElementById("plays").style.display = "none"; + document.getElementById("game-title").style.display = "none"; + document.getElementById("game-disp").style.display = "none"; + document.getElementById("welcome").style.display = "block"; +} Modified: trunk/Toss/WebClient/TossStyle.css =================================================================== --- trunk/Toss/WebClient/TossStyle.css 2010-12-12 20:24:21 UTC (rev 1248) +++ trunk/Toss/WebClient/TossStyle.css 2010-12-12 23:31:07 UTC (rev 1249) @@ -75,19 +75,6 @@ border-width: 5px 0px 0px 0px; } -#sidebar { - float: left; - width: 8.2em; - color: #ffe4aa; - background-color: #400827; - margin-top: 1em; - margin-left: 0em; - padding-left: 0.1em; - border: 1px solid #260314; - -moz-border-radius: 8px; - -webkit-border-radius: 8px; -} - #menu-top-par { margin-top: 0.5em; margin-bottom: 0em; @@ -100,39 +87,33 @@ margin-bottom: 0.5em; } -#sidebar button { - text-align: left; - border: none; +#topbar a { font-weight: bold; text-decoration: none; color: #ffe4aa; - background-color: #400827; width: 100%; } -#sidebar a { - font-weight: bold; - text-decoration: none; - color: #ffe4aa; - width: 100%; -} - -#sidebar a:hover { +#topbar a:hover { color: #b5bf8f; } -#sidebar .game-highlighted { - color: #b5bf8f; -} - /* Content */ +.game_list { + font-weight: bold; +} + +.game_list a { + font-weight: normal; +} + #main { margin-top: 2.5em; color: #260314; background-color: #ffe4aa; - margin-left: 9em; + margin-left: 1em; margin-right: 1em; padding: 1em; min-height: 100%; @@ -239,11 +220,6 @@ border-right: 1px solid #260314; } -#board-disp { - position: relative; - display: none; -} - #board { position: absolute; left: 9em; @@ -302,9 +278,7 @@ } #plays { - position: absolute; - left: 30em; - top: 0px; + display: none; padding-left: 1em; } Modified: trunk/Toss/WebClient/index.html =================================================================== --- trunk/Toss/WebClient/index.html 2010-12-12 20:24:21 UTC (rev 1248) +++ trunk/Toss/WebClient/index.html 2010-12-12 23:31:07 UTC (rev 1249) @@ -15,16 +15,17 @@ <body onload="startup()"> <div id="top"> -<div id="logo"><a href="http://www.tplay.org">tPlay</a></div> +<div id="logo"><a href="index.html">tPlay</a></div> <div id="topbar"> <span id="topuser"></span> <form id="loginform" style="display: inline;"> Username: <input type="text" name="username" id="username" /> + Password: <input type="password" name="password" id="password" /> <a id="login" href="#" onclick="login()">Login</a> -<a href="register.html">Register</a> +(<a href="register.html">Register</a>) </form> <span id="topright"> <a id="logout" href="#" onclick="logout()">Logout</a> @@ -32,27 +33,6 @@ </div> </div> -<div id="sidebar"> -<p id="menu-top-par"><span style="font-weight: bold;">Games:</span></p> -<ul id="menu-list"> - <li class="menu-list-item"> - <a id="Breakthrough" href="#" onclick="game_click('Breakthrough')">Breakthrough</a> - </li> - <li class="menu-list-item"> - <a id="Chess" href="#" onclick="game_click('Chess')">Chess</a> - </li> - <li class="menu-list-item"> - <a id="Entanglement" href="#" onclick="game_click('Entanglement')">Entanglement</a> - </li> - <li class="menu-list-item"> - <a id="Gomoku" href="#" onclick="game_click('Gomoku')">Gomoku</a> - </li> - <li class="menu-list-item"> - <a id="Tic-Tac-Toe" href="#" onclick="game_click('Tic-Tac-Toe')">Tic-Tac-Toe</a> - </li> -</ul> -</div> - <div id="main"> <div id="opponents"> @@ -64,15 +44,10 @@ <div id="welcome" class="hyphenate"> <p id="welcome-top">Enjoy games on <span class="logo-in">tPlay</span></p> -<p class="short">Strategic games are fun. Analyzing your plays you can improve -your strength and reasoning skills. On <span class="logo-in">tPlay</span> -you will enjoy the most challenging games.</p> -<ul id="features-list"> -<li>Login through Facebook on the upper right</li> -<li>Choose a game from the list — one you like or a new one to learn</li> -<li>Your plays are saved so you can analyze and restart them</li> -<li>Play against your Friends or against yourself to improve your strength</li> -<ul> +<p class="short"> + Strategic games are fun! + <a href="register.html">Register</a>, login and enjoy + <span class="logo-in">tPlay</span>!</p> </div> <div id="nosvg" class="hyphenate short" @@ -96,71 +71,53 @@ <div id="game-title"></div> +<div id="plays"> + <p> + <a href="http://en.wikipedia.org/wiki/Breakthrough_(board_game)" + class="game_list">Breakthrough</a> + (<a href="#" onclick="new_play ('Breakthrough')">New Game</a>) + </p> + <ul id="plays-list-Breakthrough"></ul> + <p> + <a class="game_list" href="http://en.wikipedia.org/wiki/Chess">Chess</a> + (<a href="#" onclick="new_play ('Chess')">New Game</a>) + </p> + <ul id="plays-list-Chess"></ul> + <p> + <a href="http://en.wikipedia.org/wiki/Entanglement_(graph_measure)" + class="game_list">Entanglement</a> + (<a href="#" onclick="new_play ('Entanglement')">New Game</a>) + </p> + <ul id="plays-list-Entanglement"></ul> + <p> + <a href="http://en.wikipedia.org/wiki/Gomoku" + class="game_list">Gomoku</a> + (<a href="#" onclick="new_play ('Gomoku')">New Game</a>) + </p> + <ul id="plays-list-Gomoku"></ul> + <p> + <a href="http://en.wikipedia.org/wiki/Tic-tac-toe" + class="game_list">Tic-Tac-Toe</a> + (<a href="#" onclick="new_play ('Tic-Tac-Toe')">New Game</a>) + </p> + <ul id="plays-list-Tic-Tac-Toe"></ul> +</div> + + <div id="opening" style="display: none;">Opening may take some time ...</div> <div id="game-disp"> - <div id="game-desc" class="hyphenate"> - <div id="Breakthrough-desc" style="display: none;"> - <p><a href="http://en.wikipedia.org/wiki/Breakthrough_(board_game)"">Breakthrough</a> is - a modern game in which the players attempt to get through the pieces of the opponent - and reach the other end of the board. The pieces move one space straight forward if the - target square is empty or one space diagonally forward, possibly beating opponents piece.</p> - <p>Even with these simple rules, Breakthrough is an interesting game in which a good - strategy requires to balance attacking pivotal pieces of the opponent and organizing - your own defensive patterns. Play yourself to see how challenging this can be.</p> + <div id="move"> + <div id="play-no-div">Game <span id="play-number">?</span></div> + Active player:<br/> + <div id="cur-player"></div> + Chosen move:<br/> + <div id="cur-move">none</div> + <div id="mk-move"> + <a href="#" onclick="make_move ()">Make move</a> </div> - <div id="Chess-desc" style="display: none;"> - <p><a href="http://en.wikipedia.org/wiki/Chess">Chess</a>, - the great classical game.</p> - </div> - <div id="Entanglement-desc" style="display: none;"> - <p><a href="http://en.wikipedia.org/wiki/Entanglement_(graph_measure)">Entanglement</a> is a game - in which a number of cops attempt to capture a robber. In each step, the cops are informed - about the current position of the robber and one of the cops may decide to fly there. - The robber on the other hand must then choose a road and get away to another position.</p> - <p>Entanglement started as a game which gives insight into how the network of roads is - intertwined. But in many cases playing it is really challenging — try capturing - a robber on a 9×2 grid with three cops to see why.</p> - </div> - <div id="Gomoku-desc" style="display: none;"> - <p><a href="http://en.wikipedia.org/wiki/Gomoku">Gomoku</a>, also known as five in a row, - is a strategic game in which each player tries to get 5 of his or her stones in a row, - horizontally, vertically, or diagonally. It is played on various board sizes and often - with additional rules, but we stick to the free-style version.</p> - <p>Gomoku has been solved for 15×15 boards, on which the starting player has - a winning strategy, and on 6×6 boards, where both players can ensure a draw. - Even though the starting player clearly has an advantage, it is challenging to win - and on an 8×8 board an interesting fight for a draw often takes place.</p> - </div> - <div id="Tic-Tac-Toe-desc" style="display: none;"> - <p><a href="http://en.wikipedia.org/wiki/Tic-tac-toe">Tic-Tac-Toe</a> is a very - simple game in which the objective of one player is to get three consecutive - crosses in a horizontal, vertical or diagonal row, and the other player attempts - the same with circles.</p> - <p>This game is not very interesting to play — both players can force a draw - with a strategy which is not hard to figure out. But exactly this simplicity - can be exploited for educational purposes, e.g. to explain concepts about games - on example plays.</p> - </div> </div> - <div id="board-disp"> - <div id="move"> - <div id="play-no-div">Play <span id="play-number">?</span></div> - Active player:<br/> - <div id="cur-player"></div> - Chosen move:<br/> - <div id="cur-move">none</div> - <div id="mk-move"> - <a href="#" onclick="make_move ()">Make move</a> - </div> - </div> - <div id="board"><div id="working">Working...</div></div> - </div> - <div id="plays"> - <div id="plays-txt">Plays:</div> - <ul id="plays-list"></ul> - <a href="#" onclick="new_play ()">Create new play</a> - </div> + <div id="board"><div id="working">Working...</div></div> </div> </div> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |