[Toss-devel-svn] SF.net SVN: toss:[1541] trunk/Toss/GGP
Status: Beta
Brought to you by:
lukaszkaiser
From: <luk...@us...> - 2011-08-16 14:50:00
|
Revision: 1541 http://toss.svn.sourceforge.net/toss/?rev=1541&view=rev Author: lukstafi Date: 2011-08-16 14:49:54 +0000 (Tue, 16 Aug 2011) Log Message: ----------- GDL translation fixing: minor Prolog integration bugs, adding non-terminal-state condition to rules, minor move translation bugs. Modified Paths: -------------- trunk/Toss/GGP/GDL.ml trunk/Toss/GGP/GDL.mli trunk/Toss/GGP/TranslateGame.ml trunk/Toss/GGP/TranslateGameTest.ml trunk/Toss/GGP/tests/connect5-raw.toss trunk/Toss/GGP/tests/connect5-simpl.toss trunk/Toss/GGP/tests/tictactoe-raw.toss trunk/Toss/GGP/tests/tictactoe-simpl.toss Modified: trunk/Toss/GGP/GDL.ml =================================================================== --- trunk/Toss/GGP/GDL.ml 2011-08-16 11:29:29 UTC (rev 1540) +++ trunk/Toss/GGP/GDL.ml 2011-08-16 14:49:54 UTC (rev 1541) @@ -235,6 +235,30 @@ (List.map (subst_one sb1) terms2) | _ -> raise Not_found + +(** A "blank" term. *) +let blank = Const "_BLANK_" + +(* Match terms on the left to ground terms on the right, ignoring + [Const "_BLANK_"] on the right. *) +let rec match_nonblank sb terms1 terms2 = + match terms1, terms2 with + | [], [] -> sb + | Const a::terms1, Const b::terms2 when a=b -> + match_nonblank sb terms1 terms2 + | Func (f,args1)::terms1, Func (g,args2)::terms2 when f=g -> + match_nonblank sb (Array.to_list args1 @ terms1) + (Array.to_list args2 @ terms2) + | _::terms1, Const "_BLANK_"::terms2 -> + match_nonblank sb terms1 terms2 + | Var x::terms1, c::terms2 -> + let sb1 = x, c in + match_nonblank (sb1::List.map (fun (x,t)->x, subst_one sb1 t) sb) + (List.map (subst_one sb1) terms1) + (List.map (subst_one sb1) terms2) + | _ -> raise Not_found + + let unify_args ?(sb=[]) args1 args2 = unify sb (Array.to_list args1) (Array.to_list args2) @@ -1422,10 +1446,7 @@ let pred_on_path_subterm path subterm = path_str path ^ term_to_name subterm -(** A "blank" term. *) -let blank = Const "_BLANK_" - (* [expand_path_vars_by prepare_lits p ts clauses] expands variables that have occurrences at path [p] in some state term of a clause (from which pre-processed literals are extracted by Modified: trunk/Toss/GGP/GDL.mli =================================================================== --- trunk/Toss/GGP/GDL.mli 2011-08-16 11:29:29 UTC (rev 1540) +++ trunk/Toss/GGP/GDL.mli 2011-08-16 14:49:54 UTC (rev 1541) @@ -62,6 +62,9 @@ type substitution = (string * term) list val unify : substitution -> term list -> term list -> substitution +(** Match terms on the left to ground terms on the right, ignoring + [Const "_BLANK_"] on the right. *) +val match_nonblank : substitution -> term list -> term list -> substitution val unify_all : substitution -> term list -> substitution val rels_unify : rel_atom -> rel_atom -> bool val subst : substitution -> term -> term Modified: trunk/Toss/GGP/TranslateGame.ml =================================================================== --- trunk/Toss/GGP/TranslateGame.ml 2011-08-16 11:29:29 UTC (rev 1540) +++ trunk/Toss/GGP/TranslateGame.ml 2011-08-16 14:49:54 UTC (rev 1541) @@ -346,7 +346,7 @@ let tup = Array.of_list (List.map2 at_path etup ptup) in if rel = "EQ_" && arity = 2 && tup.(0) = tup.(1) || (* List.mem (rel, tup) static_base *) - run_prolog_check_atom (rel, tup) program + rel <> "EQ_" && run_prolog_check_atom (rel, tup) program then ( stable_rels := Aux.Strings.add fact_rel !stable_rels; Structure.add_rel_named_elems struc fact_rel @@ -967,6 +967,7 @@ (* {{{ log entry *) if !debug_level > 1 then ( Printf.printf "filter_rule_cands: generating states...\n%!"; + (* GDL.debug_level := 4; *) ); (* }}} *) let states = Aux.fold_n @@ -977,6 +978,7 @@ states @ acc) [] !playouts_for_rule_filtering in (* {{{ log entry *) if !debug_level > 1 then ( + (* GDL.debug_level := 0; *) Printf.printf "filter_rule_cands: generated %d states.\n%!" (List.length states) ); @@ -1132,7 +1134,10 @@ let case_precond = (* singleton disjunct, i.e. no disjunction *) TranslateFormula.translate transl_data [case_cond] in - let precond = Formula.And (synch_precond @ [case_precond]) in + (* a defined relation for checking game termination *) + let nonterminal = Formula.Not (Formula.Rel ("terminal", [||])) in + let precond = + Formula.And (nonterminal :: synch_precond @ [case_precond]) in (* {{{ log entry *) if !debug_level > 2 then ( Printf.printf "build_toss_rule: synch precond = %s; main precond = %s\n%!" @@ -1429,7 +1434,7 @@ let clauses = GDL.ground_vars_at_paths prepare_lits ground_at_f_paths clauses in let defined_rels = Aux.list_diff defined_rels - ["goal"; "legal"; "next"; "terminal"] in + ["goal"; "legal"; "next"] in let defined_rels, clauses = elim_ground_args defined_rels clauses in let next_cls = Aux.map_some (function @@ -1439,8 +1444,11 @@ clauses in (* For determining turn-based we could use the original program, but for filtering the rule candidates we need the transformed - clauses. *) - let program = preprocess_program clauses in + clauses. We restore the frame clauses. *) + let program = preprocess_program + (List.map (fun ((rel,args),body as cl)-> + if rel = "frame next" then ("next", args), body + else cl) clauses) in let turn_data = try Some (check_turn_based players program) with Not_turn_based -> None in @@ -1581,7 +1589,6 @@ ) fixed_inst in let precond = Formula.And (anchors @ [rdata.precond]) in (* {{{ log entry *) - if !debug_level > 2 then ( Printf.printf "GDL.translate_incoming_move: rule=%s; trying precond=\n%s\n...%!" @@ -1595,6 +1602,13 @@ ~emb_rels:fluents ~signat ~struc_elems:rdata.struc_elems in let lhs_struc = rule.DiscreteRule.lhs_struc in let rule = DiscreteRule.compile_rule signat [] rule in + (* {{{ log entry *) + if !debug_level > 3 then ( + Printf.printf + "GDL.translate_incoming_move: struc=\n%s\n%!" + (Structure.str struc) + ); + (* }}} *) let asgns = DiscreteRule.find_matchings struc rule in (* {{{ log entry *) @@ -1781,10 +1795,18 @@ let sb = try List.fold_left (fun sb (v_term, e_term) -> - unify sb [e_term] [v_term]) [] emb - with Not_found -> failwith - ("GDL.translate_outgoing_move: inconsistent match for rule " - ^rname) in + match_nonblank sb [v_term] [e_term]) [] emb + with Not_found -> + (* {{{ log entry *) + if !debug_level > 0 then ( + Printf.printf "translate_outgoing_move: inconsistent sb: %s\n%!" + (String.concat "; "(List.map (fun (vt, et) -> + term_str vt ^"<-"^term_str et) emb)) + ); + (* }}} *) + failwith + ("GDL.translate_outgoing_move: inconsistent match for rule " + ^rname) in let legal_term = if Array.length tossrule.legal_tuple > 1 then tossrule.legal_tuple.(gdl.playing_as) Modified: trunk/Toss/GGP/TranslateGameTest.ml =================================================================== --- trunk/Toss/GGP/TranslateGameTest.ml 2011-08-16 11:29:29 UTC (rev 1540) +++ trunk/Toss/GGP/TranslateGameTest.ml 2011-08-16 14:49:54 UTC (rev 1541) @@ -50,18 +50,15 @@ let game = load_rules ("./GGP/examples/"^game_name^".gdl") in let gdl, res = TranslateGame.translate_game ~playing_as:(Const player) game in - let goal_name = - (*if !GDL.prune_rulecands_at = GDL.Never - then game_name^"-simpl-unpruned.toss" - else if !GDL.prune_rulecands_at = GDL.After_simpl - then game_name^"-simpl-pruned.toss" - else *) game_name^"-simpl.toss" in - let goal = state_of_file ("./GGP/tests/"^goal_name) in + let goal_name = game_name^"-simpl.toss" in + (* let goal = state_of_file ("./GGP/tests/"^goal_name) in *) + let goal_str = Aux.input_file (open_in ("./GGP/tests/"^goal_name)) in let resf = open_out ("./GGP/tests/"^game_name^"-temp.toss") in let res_str = Arena.state_str res in output_string resf res_str; close_out resf; - let eq, msg = Arena.compare_diff goal res in + (* let eq, msg = Arena.compare_diff goal res in *) + let eq, msg = goal_str = res_str, "sorry, just comparing as strings" in assert_bool ("GGP/examples/"^game_name^".gdl to GGP/tests/"^goal_name^ ", see GGP/tests/"^game_name^"-temp.toss: "^msg) @@ -99,15 +96,15 @@ (fun () -> game_test_case ~game_name:"tictactoe" ~player:"xplayer" ~own_plnum:0 ~opponent_plnum:1 - ~loc0_rule_name:"mark_x64_y19_0" + ~loc0_rule_name:"mark_x6_y_noop" ~loc0_emb:[ - "cell_x64_y19__blank_", "cell_2_2_MV1"; - "control__blank_", "control_MV1"] + "cell_x6_y__BLANK_", "cell_2_2__BLANK_"; + "control__BLANK_", "control__BLANK_"] ~loc0_move:"(mark 2 2)" ~loc0_noop:"noop" - ~loc1:1 ~loc1_rule_name:"mark_x71_y26_1" + ~loc1:1 ~loc1_rule_name:"noop_mark_x7_y0" ~loc1_emb:[ - "cell_x71_y26__blank_", "cell_1_1_MV1"; - "control__blank_", "control_MV1"] + "cell_x7_y0__BLANK_", "cell_1_1__BLANK_"; + "control__BLANK_", "control__BLANK_"] ~loc1_noop:"noop" ~loc1_move:"(mark 1 1)" ); @@ -175,7 +172,7 @@ "control__blank_", "control_MV1"] ~loc1_noop:"noop" ~loc1_move:"(mark f g)" ); - +(* "breakthrough" >:: (fun () -> game_test_case ~game_name:"breakthrough" ~player:"white" @@ -214,10 +211,11 @@ "control__blank_", "control_MV1"] ~loc1_noop:"noop" ~loc1_move:"(mark f g)" ); +*) ] let a () = - GDL.debug_level := 2; + (* GDL.debug_level := 4; *) TranslateGame.debug_level := 4; GameSimpl.debug_level := 4; DiscreteRule.debug_level := 4; @@ -225,18 +223,18 @@ let a () = - game_test_case ~game_name:"connect5" ~player:"x" + game_test_case ~game_name:"tictactoe" ~player:"xplayer" ~own_plnum:0 ~opponent_plnum:1 - ~loc0_rule_name:"mark_x161_y162_0" + ~loc0_rule_name:"mark_x6_y_noop" ~loc0_emb:[ - "cell_x161_y162__blank_", "cell_e_f_MV1"; - "control__blank_", "control_MV1"] - ~loc0_move:"(mark e f)" ~loc0_noop:"noop" - ~loc1:1 ~loc1_rule_name:"mark_x175_y176_1" + "cell_x6_y__BLANK_", "cell_2_2__BLANK_"; + "control__BLANK_", "control__BLANK_"] + ~loc0_move:"(mark 2 2)" ~loc0_noop:"noop" + ~loc1:1 ~loc1_rule_name:"noop_mark_x7_y0" ~loc1_emb:[ - "cell_x175_y176__blank_", "cell_f_g_MV1"; - "control__blank_", "control_MV1"] - ~loc1_noop:"noop" ~loc1_move:"(mark f g)" + "cell_x7_y0__BLANK_", "cell_1_1__BLANK_"; + "control__BLANK_", "control__BLANK_"] + ~loc1_noop:"noop" ~loc1_move:"(mark 1 1)" let a () = @@ -272,7 +270,7 @@ TranslateGame.generate_test_case := None let a () = - regenerate ~debug:true ~game_name:"tictactoe" ~player:"xplayer"; + regenerate ~debug:false ~game_name:"tictactoe" ~player:"xplayer"; (* regenerate ~debug:false ~game_name:"connect5" ~player:"x"; *) (* regenerate ~debug:true ~game_name:"breakthrough" ~player:"white"; *) (* regenerate ~debug:true ~game_name:"pawn_whopping" ~player:"x"; *) Modified: trunk/Toss/GGP/tests/connect5-raw.toss =================================================================== --- trunk/Toss/GGP/tests/connect5-raw.toss 2011-08-16 11:29:29 UTC (rev 1540) +++ trunk/Toss/GGP/tests/connect5-raw.toss 2011-08-16 14:49:54 UTC (rev 1541) @@ -408,6 +408,9 @@ cell__BLANK___BLANK___BLANK_(cell_d_y8__BLANK_) and cell_2x(cell_e_y8__BLANK_) and cell__BLANK___BLANK___BLANK_(cell_e_y8__BLANK_)) +REL terminal() = + (true and not exists_empty_cell() and true) or + (true and exists_line_of_five() and true) PLAYERS x, o RULE mark_x5_y5_noop: [cell_x5_y5__BLANK_, control__BLANK_ | @@ -422,7 +425,7 @@ ] -> [cell_x5_y5__BLANK_, control__BLANK_ | cell_2x (cell_x5_y5__BLANK_); control_0o (control__BLANK_) | - ] emb cell_2b, cell_2o, cell_2x, control_0o, control_0x + ] emb cell_2b, cell_2o, cell_2x, control_0o, control_0x pre not terminal() RULE noop_mark_x6_y6: [cell_x6_y6__BLANK_, control__BLANK_ | _opt_cell_2b (control__BLANK_); @@ -436,7 +439,7 @@ ] -> [cell_x6_y6__BLANK_, control__BLANK_ | cell_2o (cell_x6_y6__BLANK_); control_0x (control__BLANK_) | - ] emb cell_2b, cell_2o, cell_2x, control_0o, control_0x + ] emb cell_2b, cell_2o, cell_2x, control_0o, control_0x pre not terminal() LOC 0 { PLAYER x { Modified: trunk/Toss/GGP/tests/connect5-simpl.toss =================================================================== --- trunk/Toss/GGP/tests/connect5-simpl.toss 2011-08-16 11:29:29 UTC (rev 1540) +++ trunk/Toss/GGP/tests/connect5-simpl.toss 2011-08-16 14:49:54 UTC (rev 1541) @@ -204,6 +204,7 @@ not control__BLANK_(cell_c1_y8__BLANK_) and not control__BLANK_(cell_d_y8__BLANK_) and not control__BLANK_(cell_e_y8__BLANK_)) +REL terminal() = exists_line_of_five() or not exists_empty_cell() PLAYERS x, o DATA R2: EQ___cell_1__cell_1__AND__nextcol__cell_0__cell_0, R0: nextcol__cell_0__cell_0__AND__nextcol__cell_1__cell_1, @@ -221,7 +222,7 @@ ] -> [cell_x5_y5__BLANK_, control__BLANK_ | cell_2x (cell_x5_y5__BLANK_); control_0o (control__BLANK_) | - ] emb cell_2b, cell_2o, cell_2x, control_0o, control_0x + ] emb cell_2b, cell_2o, cell_2x, control_0o, control_0x pre not terminal() RULE noop_mark_x6_y6: [cell_x6_y6__BLANK_, control__BLANK_ | _opt_cell_2b (control__BLANK_); @@ -234,7 +235,7 @@ ] -> [cell_x6_y6__BLANK_, control__BLANK_ | cell_2o (cell_x6_y6__BLANK_); control_0x (control__BLANK_) | - ] emb cell_2b, cell_2o, cell_2x, control_0o, control_0x + ] emb cell_2b, cell_2o, cell_2x, control_0o, control_0x pre not terminal() LOC 0 { PLAYER x { PAYOFF 100. * :(conn5__x()) + 50. * :(not exists_line_of_five()) Modified: trunk/Toss/GGP/tests/tictactoe-raw.toss =================================================================== --- trunk/Toss/GGP/tests/tictactoe-raw.toss 2011-08-16 11:29:29 UTC (rev 1540) +++ trunk/Toss/GGP/tests/tictactoe-raw.toss 2011-08-16 14:49:54 UTC (rev 1541) @@ -186,6 +186,9 @@ cell__BLANK___BLANK___BLANK_(cell_m4_2__BLANK_) and cell_13(cell_m4_3__BLANK_) and cell_2x(cell_m4_3__BLANK_) and cell__BLANK___BLANK___BLANK_(cell_m4_3__BLANK_)) +REL terminal() = + (true and not open() and true) or (true and line__o() and true) or + (true and line__x() and true) PLAYERS xplayer, oplayer RULE mark_x6_y_noop: [cell_x6_y__BLANK_, control__BLANK_ | @@ -202,23 +205,7 @@ cell_2x (cell_x6_y__BLANK_); control_0oplayer (control__BLANK_) | ] emb cell_2b, cell_2o, cell_2x, control_0oplayer, control_0xplayer -RULE mark_x6_y_noop0: - [cell_x6_y__BLANK_, control__BLANK_ | - _opt_cell_2b (control__BLANK_); - _opt_cell_2o {cell_x6_y__BLANK_; control__BLANK_}; - _opt_cell_2x {cell_x6_y__BLANK_; control__BLANK_}; - _opt_control_0oplayer (cell_x6_y__BLANK_); - _opt_control_0xplayer (cell_x6_y__BLANK_); cell_2b (cell_x6_y__BLANK_); - cell__BLANK___BLANK___BLANK_ (cell_x6_y__BLANK_); - control_0oplayer (control__BLANK_); control_0xplayer (control__BLANK_); - control__BLANK_ (control__BLANK_) - | - ] -> - [cell_x6_y__BLANK_, control__BLANK_ | - cell_2x (cell_x6_y__BLANK_); control_0oplayer (control__BLANK_); - control_0xplayer (control__BLANK_) - | - ] emb cell_2b, cell_2o, cell_2x, control_0oplayer, control_0xplayer + pre not terminal() RULE noop_mark_x7_y0: [cell_x7_y0__BLANK_, control__BLANK_ | _opt_cell_2b (control__BLANK_); @@ -234,23 +221,7 @@ cell_2o (cell_x7_y0__BLANK_); control_0xplayer (control__BLANK_) | ] emb cell_2b, cell_2o, cell_2x, control_0oplayer, control_0xplayer -RULE noop_mark_x7_y00: - [cell_x7_y0__BLANK_, control__BLANK_ | - _opt_cell_2b (control__BLANK_); - _opt_cell_2o {cell_x7_y0__BLANK_; control__BLANK_}; - _opt_cell_2x {cell_x7_y0__BLANK_; control__BLANK_}; - _opt_control_0oplayer (cell_x7_y0__BLANK_); - _opt_control_0xplayer (cell_x7_y0__BLANK_); cell_2b (cell_x7_y0__BLANK_); - cell__BLANK___BLANK___BLANK_ (cell_x7_y0__BLANK_); - control_0oplayer (control__BLANK_); control_0xplayer (control__BLANK_); - control__BLANK_ (control__BLANK_) - | - ] -> - [cell_x7_y0__BLANK_, control__BLANK_ | - cell_2o (cell_x7_y0__BLANK_); control_0oplayer (control__BLANK_); - control_0xplayer (control__BLANK_) - | - ] emb cell_2b, cell_2o, cell_2x, control_0oplayer, control_0xplayer + pre not terminal() LOC 0 { PLAYER xplayer { @@ -258,7 +229,7 @@ 100. * :((true and line__x() and true)) + 50. * :((true and not line__x() and not line__o() and not open() and true)) - MOVES [mark_x6_y_noop -> 1]; [mark_x6_y_noop0 -> 1] } + MOVES [mark_x6_y_noop -> 1] } PLAYER oplayer { PAYOFF 100. * :((true and line__o() and true)) + @@ -279,7 +250,7 @@ 100. * :((true and line__o() and true)) + 50. * :((true and not line__x() and not line__o() and not open() and true)) - MOVES [noop_mark_x7_y0 -> 0]; [noop_mark_x7_y00 -> 0] } + MOVES [noop_mark_x7_y0 -> 0] } } MODEL [cell_1_1__BLANK_, cell_1_2__BLANK_, cell_1_3__BLANK_, cell_2_1__BLANK_, Modified: trunk/Toss/GGP/tests/tictactoe-simpl.toss =================================================================== --- trunk/Toss/GGP/tests/tictactoe-simpl.toss 2011-08-16 11:29:29 UTC (rev 1540) +++ trunk/Toss/GGP/tests/tictactoe-simpl.toss 2011-08-16 14:49:54 UTC (rev 1541) @@ -115,6 +115,7 @@ v0 = cell_m4_1__BLANK_ and not control__BLANK_(cell_m4_1__BLANK_) and not control__BLANK_(cell_m4_2__BLANK_) and not control__BLANK_(cell_m4_3__BLANK_)) +REL terminal() = line__o() or line__x() or not open() PLAYERS xplayer, oplayer DATA R3: cell_03__AND__cell_11, R2: cell_01__AND__cell_13, R1: cell_03__AND__cell_13, R0: cell_02__AND__cell_12, @@ -133,22 +134,7 @@ cell_2x (cell_x6_y__BLANK_); control_0oplayer (control__BLANK_) | ] emb cell_2b, cell_2o, cell_2x, control_0oplayer, control_0xplayer -RULE mark_x6_y_noop0: - [cell_x6_y__BLANK_, control__BLANK_ | - _opt_cell_2b (control__BLANK_); - _opt_cell_2o {cell_x6_y__BLANK_; control__BLANK_}; - _opt_cell_2x {cell_x6_y__BLANK_; control__BLANK_}; - _opt_control_0oplayer (cell_x6_y__BLANK_); - _opt_control_0xplayer (cell_x6_y__BLANK_); cell_2b (cell_x6_y__BLANK_); - control_0oplayer (control__BLANK_); control_0xplayer (control__BLANK_); - control__BLANK_ (control__BLANK_) - | - ] -> - [cell_x6_y__BLANK_, control__BLANK_ | - cell_2x (cell_x6_y__BLANK_); control_0oplayer (control__BLANK_); - control_0xplayer (control__BLANK_) - | - ] emb cell_2b, cell_2o, cell_2x, control_0oplayer, control_0xplayer + pre not terminal() RULE noop_mark_x7_y0: [cell_x7_y0__BLANK_, control__BLANK_ | _opt_cell_2b (control__BLANK_); @@ -163,29 +149,14 @@ cell_2o (cell_x7_y0__BLANK_); control_0xplayer (control__BLANK_) | ] emb cell_2b, cell_2o, cell_2x, control_0oplayer, control_0xplayer -RULE noop_mark_x7_y00: - [cell_x7_y0__BLANK_, control__BLANK_ | - _opt_cell_2b (control__BLANK_); - _opt_cell_2o {cell_x7_y0__BLANK_; control__BLANK_}; - _opt_cell_2x {cell_x7_y0__BLANK_; control__BLANK_}; - _opt_control_0oplayer (cell_x7_y0__BLANK_); - _opt_control_0xplayer (cell_x7_y0__BLANK_); cell_2b (cell_x7_y0__BLANK_); - control_0oplayer (control__BLANK_); control_0xplayer (control__BLANK_); - control__BLANK_ (control__BLANK_) - | - ] -> - [cell_x7_y0__BLANK_, control__BLANK_ | - cell_2o (cell_x7_y0__BLANK_); control_0oplayer (control__BLANK_); - control_0xplayer (control__BLANK_) - | - ] emb cell_2b, cell_2o, cell_2x, control_0oplayer, control_0xplayer + pre not terminal() LOC 0 { PLAYER xplayer { PAYOFF 100. * :(line__x()) + 50. * :((not line__o() and not line__x() and not open())) - MOVES [mark_x6_y_noop -> 1]; [mark_x6_y_noop0 -> 1] } + MOVES [mark_x6_y_noop -> 1] } PLAYER oplayer { PAYOFF 100. * :(line__o()) + @@ -203,7 +174,7 @@ PAYOFF 100. * :(line__o()) + 50. * :((not line__o() and not line__x() and not open())) - MOVES [noop_mark_x7_y0 -> 0]; [noop_mark_x7_y00 -> 0] } + MOVES [noop_mark_x7_y0 -> 0] } } MODEL [cell_1_1__BLANK_, cell_1_2__BLANK_, cell_1_3__BLANK_, cell_2_1__BLANK_, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |