diff --git a/chess_gui/.dancer b/chess_gui/.dancer new file mode 100644 index 0000000..e69de29 diff --git a/chess_gui/MANIFEST b/chess_gui/MANIFEST new file mode 100644 index 0000000..3d0e9a8 --- /dev/null +++ b/chess_gui/MANIFEST @@ -0,0 +1,24 @@ +MANIFEST +MANIFEST.SKIP +Makefile.PL +cpanfile +config.yml +.dancer +bin/app.psgi +t/001_base.t +t/002_index_route.t +views/index.tt +public/dispatch.fcgi +public/favicon.ico +public/500.html +public/dispatch.cgi +public/404.html +lib/chess_gui.pm +environments/development.yml +environments/production.yml +views/layouts/main.tt +public/javascripts/jquery.js +public/css/style.css +public/css/error.css +public/images/perldancer-bg.jpg +public/images/perldancer.jpg diff --git a/chess_gui/MANIFEST.SKIP b/chess_gui/MANIFEST.SKIP new file mode 100644 index 0000000..c32318f --- /dev/null +++ b/chess_gui/MANIFEST.SKIP @@ -0,0 +1,17 @@ +^\.git\/ +maint +^tags$ +.last_cover_stats +Makefile$ +^blib +^pm_to_blib +^.*.bak +^.*.old +^t.*sessions +^cover_db +^.*\.log +^.*\.swp$ +MYMETA.* +^.gitignore +^.svn\/ +^chess_gui- diff --git a/chess_gui/Makefile.PL b/chess_gui/Makefile.PL new file mode 100644 index 0000000..33144d0 --- /dev/null +++ b/chess_gui/Makefile.PL @@ -0,0 +1,26 @@ +use strict; +use warnings; +use ExtUtils::MakeMaker; + +# Normalize version strings like 6.30_02 to 6.3002, +# so that we can do numerical comparisons on it. +my $eumm_version = $ExtUtils::MakeMaker::VERSION; +$eumm_version =~ s/_//; + +WriteMakefile( + NAME => 'chess_gui', + AUTHOR => q{YOUR NAME }, + VERSION_FROM => 'lib/chess_gui.pm lib/chess_gui.pm', + ABSTRACT => 'YOUR APPLICATION ABSTRACT', + ($eumm_version >= 6.3001 + ? ('LICENSE'=> 'perl') + : ()), + PL_FILES => {}, + PREREQ_PM => { + 'Test::More' => 0, + 'YAML' => 0, + 'Dancer2' => 0.400000, + }, + dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, + clean => { FILES => 'chess_gui-*' }, +); diff --git a/chess_gui/bin/app.psgi b/chess_gui/bin/app.psgi new file mode 100755 index 0000000..d5b0c76 --- /dev/null +++ b/chess_gui/bin/app.psgi @@ -0,0 +1,45 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use FindBin; +use lib "$FindBin::Bin/../lib"; + + +# use this block if you don't need middleware, and only have a single target Dancer app to run here +use chess_gui; + +chess_gui->to_app; + +=begin comment +# use this block if you want to include middleware such as Plack::Middleware::Deflater + +use chess_gui; +use Plack::Builder; + +builder { + enable 'Deflater'; + chess_gui->to_app; +} + +=end comment + +=cut + +=begin comment +# use this block if you want to mount several applications on different path + +use chess_gui; +use chess_gui_admin; + +use Plack::Builder; + +builder { + mount '/' => chess_gui->to_app; + mount '/admin' => chess_gui_admin->to_app; +} + +=end comment + +=cut + diff --git a/chess_gui/config.yml b/chess_gui/config.yml new file mode 100644 index 0000000..7e076cf --- /dev/null +++ b/chess_gui/config.yml @@ -0,0 +1,71 @@ +# This is the main configuration file of your Dancer2 app +# env-related settings should go to environments/$env.yml +# all the settings in this file will be loaded at Dancer's startup. + +# === Basic configuration === + +# Your application's name +appname: "chess_gui" + +# The default layout to use for your application (located in +# views/layouts/main.tt) +#layout: "main" + +# when the charset is set to UTF-8 Dancer2 will handle for you +# all the magic of encoding and decoding. You should not care +# about unicode within your app when this setting is set (recommended). +charset: "UTF-8" + +# === Engines === +# +# NOTE: All the engine configurations need to be under a single "engines:" +# key. If you uncomment engine configurations below, make sure to delete +# all "engines:" lines except the first. Otherwise, only the last +# "engines:" block will take effect. + +# template engine +# simple: default and very basic template engine +# template_toolkit: TT + +#template: "simple" + +plugins: + Ajax: + content_type: 'application/json' + +template: "template_toolkit" +# engines: +# template: +# template_toolkit: +# # Note: start_tag and end_tag are regexes +# start_tag: '<%' +# end_tag: '%>' + +# session engine +# +# Simple: in-memory session store - Dancer2::Session::Simple +# YAML: session stored in YAML files - Dancer2::Session::YAML +# +# Check out metacpan for other session storage options: +# https://metacpan.org/search?q=Dancer2%3A%3ASession&search_type=modules +# +# Default value for 'cookie_name' is 'dancer.session'. If you run multiple +# Dancer apps on the same host then you will need to make sure 'cookie_name' +# is different for each app. +# + +engines: + session: +# Memcached: +# memcached_servers: +# - /var/sock/memcached +# fatal_cluster_unreachable: 0 + Simple: + cookie_name: testapp.session + +#engines: +# session: +# YAML: +# cookie_name: eshop.session +# is_secure: 1 +# is_http_only: 1 diff --git a/chess_gui/cpanfile b/chess_gui/cpanfile new file mode 100644 index 0000000..52876da --- /dev/null +++ b/chess_gui/cpanfile @@ -0,0 +1,34 @@ +requires "Dancer2" => "0.400000"; + +recommends "YAML" => "0"; +recommends "URL::Encode::XS" => "0"; +recommends "CGI::Deurl::XS" => "0"; +recommends "CBOR::XS" => "0"; +recommends "YAML::XS" => "0"; +recommends "Class::XSAccessor" => "0"; +recommends "Crypt::URandom" => "0"; +recommends "HTTP::XSCookies" => "0"; +recommends "HTTP::XSHeaders" => "0"; +recommends "Math::Random::ISAAC::XS" => "0"; +recommends "MooX::TypeTiny" => "0"; +recommends "Type::Tiny::XS" => "0"; + +feature 'accelerate', 'Accelerate Dancer2 app performance with XS modules' => sub { + requires "URL::Encode::XS" => "0"; + requires "CGI::Deurl::XS" => "0"; + requires "YAML::XS" => "0"; + requires "Class::XSAccessor" => "0"; + requires "Cpanel::JSON::XS" => "0"; + requires "Crypt::URandom" => "0"; + requires "HTTP::XSCookies" => "0"; + requires "HTTP::XSHeaders" => "0"; + requires "Math::Random::ISAAC::XS" => "0"; + requires "MooX::TypeTiny" => "0"; + requires "Type::Tiny::XS" => "0"; +}; + +on "test" => sub { + requires "Test::More" => "0"; + requires "HTTP::Request::Common" => "0"; +}; + diff --git a/chess_gui/environments/development.yml b/chess_gui/environments/development.yml new file mode 100644 index 0000000..bf826db --- /dev/null +++ b/chess_gui/environments/development.yml @@ -0,0 +1,20 @@ +# configuration file for development environment + +# the logger engine to use +# console: log messages to STDOUT (your console where you started the +# application server) +# file: log message to a file in log/ +logger: "console" + +# the log level for this environment +# core is the lowest, it shows Dancer2's core log messages as well as yours +# (debug, info, warning and error) +log: "core" + +# should Dancer2 show a stacktrace when an 5xx error is caught? +# if set to yes, public/500.html will be ignored and either +# views/500.tt, 'error_template' template, or a default error template will be used. +show_errors: 1 + +# print the banner +startup_info: 1 diff --git a/chess_gui/environments/production.yml b/chess_gui/environments/production.yml new file mode 100644 index 0000000..d86c30c --- /dev/null +++ b/chess_gui/environments/production.yml @@ -0,0 +1,13 @@ +# configuration file for production environment + +# only log warning and error messsages +log: "warning" + +# log message to a file in logs/ +logger: "file" + +# hide errors +show_errors: 0 + +# disable server tokens in production environments +no_server_tokens: 1 diff --git a/chess_gui/lib/chess_gui.pm b/chess_gui/lib/chess_gui.pm new file mode 100644 index 0000000..5351b0a --- /dev/null +++ b/chess_gui/lib/chess_gui.pm @@ -0,0 +1,867 @@ +#!/usr/bin/env perl +package chess_gui; +use Dancer2; +use Dancer2::Plugin::Ajax; +use Dancer2::Session::Memcached; # Let's use the database for session storage for now. +use Template; +use DBI; +use DBD::Pg; +use strict; +use warnings; +#use warnings FATAL => qw(uninitialized); + +# Self-learning, console-based chess game written in Perl. +# The self-learning aspect involves iterating through all chess layouts from the default chess setup. One fixed AI iterates through all valid moves, while the other AI reacts accordingly. The outcome is stored in a database for later retrieval. +# (C) Roy van Lunsen. + +our $VERSION = '37.0'; + +#sub USAGE_MSG { +# print 'Usage:', "\n"; +# print '`', $0, ' auto`: Run the chess program non-interactively.', "\n"; +# print '`', $0, ' manual`: Run the chess program interactively (i.e., you can control one side).', "\n"; +# exit 1; +#} + +#my $user_mode; +#if ($#ARGV < 0) { +# &USAGE_MSG; +#} elsif ('manual' eq $ARGV[0]) { +# $user_mode = undef; +#} elsif ('auto' eq $ARGV[0]) { +# $user_mode = -1; +#} else { +# &USAGE_MSG; +#} + +my $dbname = 'chessd'; # See ./chess.sql. +my $username = 'postgres'; +my $dbh = DBI->connect("dbi:Pg:dbname=$dbname", $username, '', {PrintError => 1, RaiseError => 1, AutoCommit => 1}) or die $?; +#my $dbh = DBI->connect("dbi:Pg:dbname=$dbname", $username, '', {PrintError => 0, RaiseError => 0, AutoCommit => 1}) or die $?; +#my $sth1 = $dbh->prepare(q/SELECT black.id, white.id, black.prio, white.prio FROM black, white WHERE black.id = white.id and white.b0 = ? and white.b1 = ? and white.k0 = ? and white.n0 = ? and white.n1 = ? and white.p0 = ? and white.p1 = ? and white.p2 = ? and white.p3 = ? and white.p4 = ? and white.p5 = ? and white.p6 = ? and white.p7 = ? and white.q0 = ? and white.r0 = ? and white.r1 = ? and black.b0 = ? and black.b1 = ? and black.k0 = ? and black.n0 = ? and black.n1 = ? and black.p0 = ? and black.p1 = ? and black.p2 = ? and black.p3 = ? and black.p4 = ? and black.p5 = ? and black.p6 = ? and black.p7 = ? and black.q0 = ? and black.r0 = ? and black.r1 = ?/); #TODO: There should be a better way to do this... +#my $sth0 = $dbh->prepare(q/SELECT bw_id, prio FROM white, context WHERE white.b0 = ? and white.b1 = ? and white.k0 = ? and white.n0 = ? and white.n1 = ? and white.p0 = ? and white.p1 = ? and white.p2 = ? and white.p3 = ? and white.p4 = ? and white.p5 = ? and white.p6 = ? and white.p7 = ? and white.q0 = ? and white.r0 = ? and white.r1 = ? and white.b0 = ? and context.b1 = ? and context.k0 = ? and context.n0 = ? and context.n1 = ? and context.p0 = ? and context.p1 = ? and context.p2 = ? and context.p3 = ? and context.p4 = ? and context.p5 = ? and context.p6 = ? and context.p7 = ? and context.q0 = ? and context.r0 = ? and context.r1 = ?/); +#my $sth1 = $dbh->prepare(q/SELECT bw_id, prio FROM black, context WHERE black.b0 = ? and black.b1 = ? and black.k0 = ? and black.n0 = ? and black.n1 = ? and black.p0 = ? and black.p1 = ? and black.p2 = ? and black.p3 = ? and black.p4 = ? and black.p5 = ? and black.p6 = ? and black.p7 = ? and black.q0 = ? and black.r0 = ? and black.r1 = ? and black.b0 = ? and context.b1 = ? and context.k0 = ? and context.n0 = ? and context.n1 = ? and context.p0 = ? and context.p1 = ? and context.p2 = ? and context.p3 = ? and context.p4 = ? and context.p5 = ? and context.p6 = ? and context.p7 = ? and context.q0 = ? and context.r0 = ? and context.r1 = ?/); +#my $sth1 = $dbh->prepare(q/SELECT black.id, white.id, bprio, wprio FROM black, white, context WHERE black.id = bid and white.id = wid and white.b0 = ? and white.b1 = ? and white.k0 = ? and white.n0 = ? and white.n1 = ? and white.p0 = ? and white.p1 = ? and white.p2 = ? and white.p3 = ? and white.p4 = ? and white.p5 = ? and white.p6 = ? and white.p7 = ? and white.q0 = ? and white.r0 = ? and white.r1 = ? and black.b0 = ? and black.b1 = ? and black.k0 = ? and black.n0 = ? and black.n1 = ? and black.p0 = ? and black.p1 = ? and black.p2 = ? and black.p3 = ? and black.p4 = ? and black.p5 = ? and black.p6 = ? and black.p7 = ? and black.q0 = ? and black.r0 = ? and black.r1 = ?/); #TODO: There should be a better way to do this... +#my $sth1 = $dbh->prepare(q/SELECT black.id, white.id FROM black, white WHERE (black.id, white.id) IN (SELECT bid, wid FROM context) and white.b0 = ? and white.b1 = ? and white.k0 = ? and white.n0 = ? and white.n1 = ? and white.p0 = ? and white.p1 = ? and white.p2 = ? and white.p3 = ? and white.p4 = ? and white.p5 = ? and white.p6 = ? and white.p7 = ? and white.q0 = ? and white.r0 = ? and white.r1 = ? and black.b0 = ? and black.b1 = ? and black.k0 = ? and black.n0 = ? and black.n1 = ? and black.p0 = ? and black.p1 = ? and black.p2 = ? and black.p3 = ? and black.p4 = ? and black.p5 = ? and black.p6 = ? and black.p7 = ? and black.q0 = ? and black.r0 = ? and black.r1 = ?/); +my $sth1 = $dbh->prepare(q/SELECT bid, wid, bprio, wprio FROM context WHERE (bid, wid) IN (SELECT black.id, white.id FROM black, white WHERE white.b0 = ? and white.b1 = ? and white.k0 = ? and white.n0 = ? and white.n1 = ? and white.p0 = ? and white.p1 = ? and white.p2 = ? and white.p3 = ? and white.p4 = ? and white.p5 = ? and white.p6 = ? and white.p7 = ? and white.q0 = ? and white.r0 = ? and white.r1 = ? and black.b0 = ? and black.b1 = ? and black.k0 = ? and black.n0 = ? and black.n1 = ? and black.p0 = ? and black.p1 = ? and black.p2 = ? and black.p3 = ? and black.p4 = ? and black.p5 = ? and black.p6 = ? and black.p7 = ? and black.q0 = ? and black.r0 = ? and black.r1 = ?)/); +#my $sth2 = $dbh->prepare(q/INSERT INTO white (b0, b1, k0, n0, n1, p0, p1, p2, p3, p4, p5, p6, p7, q0, r0, r1, prio) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)/); +#my $sth3 = $dbh->prepare(q/INSERT INTO black (b0, b1, k0, n0, n1, p0, p1, p2, p3, p4, p5, p6, p7, q0, r0, r1, prio) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)/); +#my $sth2 = $dbh->prepare(q/INSERT INTO white (b0, b1, k0, n0, n1, p0, p1, p2, p3, p4, p5, p6, p7, q0, r0, r1) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)/); +#my $sth3 = $dbh->prepare(q/INSERT INTO black (b0, b1, k0, n0, n1, p0, p1, p2, p3, p4, p5, p6, p7, q0, r0, r1) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)/); +#my $sth4 = $dbh->prepare(q/INSERT INTO context (b0, b1, k0, n0, n1, p0, p1, p2, p3, p4, p5, p6, p7, q0, r0, r1, prio) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)/); +my $sth2 = $dbh->prepare(q/INSERT INTO white (b0, b1, k0, n0, n1, p0, p1, p2, p3, p4, p5, p6, p7, q0, r0, r1) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)/); +my $sth3 = $dbh->prepare(q/INSERT INTO black (b0, b1, k0, n0, n1, p0, p1, p2, p3, p4, p5, p6, p7, q0, r0, r1) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)/); +my $sth5 = $dbh->prepare(q/INSERT INTO context (bid, wid, bprio, wprio) VALUES (?, ?, ?, ?)/); +my $sth6 = $dbh->prepare(q/SELECT id FROM white WHERE b0 = ? and b1 = ? and k0 = ? and n0 = ? and n1 = ? and p0 = ? and p1 = ? and p2 = ? and p3 = ? and p4 = ? and p5 = ? and p6 = ? and p7 = ? and q0 = ? and r0 = ? and r1 = ?/); +my $sth7 = $dbh->prepare(q/SELECT id FROM black WHERE b0 = ? and b1 = ? and k0 = ? and n0 = ? and n1 = ? and p0 = ? and p1 = ? and p2 = ? and p3 = ? and p4 = ? and p5 = ? and p6 = ? and p7 = ? and q0 = ? and r0 = ? and r1 = ?/); +my $sth8 = $dbh->prepare(q/SELECT black.b0, black.b1, black.k0, black.n0, black.n1, black.p0, black.p1, black.p2, black.p3, black.p4, black.p5, black.p6, black.p7, black.q0, black.r0, black.r1, white.b0, white.b1, white.k0, white.n0, white.n1, white.p0, white.p1, white.p2, white.p3, white.p4, white.p5, white.p6, white.p7, white.q0, white.r0, white.r1 FROM black, white WHERE (black.id, white.id) IN (SELECT bid, wid FROM sessions WHERE session = ?)/); +my $sth9 = $dbh->prepare(q/INSERT INTO sessions (session, bid, wid) VALUES ($1, $2, $3) ON CONFLICT ON CONSTRAINT sessions_pkey DO UPDATE SET (bid, wid) = ($2, $3)/); +my (@tree, @what_i_did, %prop, @keys, @pplayer, %tmpalg, %tmpalg2, %tmpalg3, %tmpalg4, $players, @not_player, $smaleer, %pval); +@not_player[0, 1] = (1, 0); +my @player = reverse @not_player; +@pplayer[0, 1] = qw/w b/; +my @pseudoinfinite_loop_check; +my $user_mode; +my $player; +my $player_turn = 0; +my $counter; +my $action_limit = 100; +my $loop_limit = 6; +my @direction = qw/1 1 1 -1 -1 -1 -1 1 0 1 0 -1 1 0 -1 0 0.5 2 0.5 -2 -0.5 -2 -0.5 2/; # Diagonal direction modifiers: $direction[0..7]. Straight direction modifiers: $direction[8..15]. Knight direction modifiers: $direction[0..7,16..23]. +my @default_iboard; +sub INTERRUPT { + $sth1->finish(); + $sth2->finish(); + $sth3->finish(); + $sth5->finish(); + $sth6->finish(); + $sth7->finish(); + $sth8->finish(); + $sth9->finish(); + $dbh->disconnect; + exit 0; +} + +$SIG{'INT'} = 'INTERRUPT'; + +sub PRETTY_CALC { # Calculate total piece value (for post-game). It used to print the chess board. + my ($pval, $player) = @_; + foreach my $secondc (0..7) { +# print "\n"; + foreach my $firstc (0..7) { + my $coordinate = $firstc.'.'.(7-$secondc); + if (defined($prop{$coordinate})) { + my $p = join '', @{$prop{$coordinate}}; + if ($prop{$coordinate}[0] == $player) { + $pval += $pval{$p}; + } else { + $pval -= $pval{$p}; + } +# printf '%-8s', $p; + } else { +# printf '%-8s', $coordinate; + } + } +# print "\n"; + } + return ($pval, $player); +} + +sub INIT_BOARD { + foreach (0..63) { # Initialize chess positions piece worth (%p${player}val). + my ($x, $y, $player); +# $_ = sprintf("%.1o",$_/10); # (This) sprintf doesn't support octal floats. + $_ = sprintf("%.1f", sprintf("%o", $_)/10); + $x = int($_); + $y = $_ * 10 % 10; # 0.x % 1 = 0 +# if ($#_ == -1) { + if ($y < 2) { # White, hereafter called player 0. + $player = 0; + } elsif ($y > 5) { # Black, hereafter called player 1. + $player = 1; + } else { + $default_iboard[$y][$x] = $_; + next; + } + if ($y*2 % 10 == 2) { # Pawn. + push @{$prop{$_}}, ($player, 'p', $x); + $pval{join '', @{$prop{$_}}} = 0.001; + } elsif ($x % 7 == 0) { # Rook. + push @{$prop{$_}}, ($player, 'r', $x / 7); + $pval{join '', @{$prop{$_}}} = 0.01; + } elsif ($x % 5 == 1) { # Knight. + push @{$prop{$_}}, ($player, 'n', ($x-1) / 5); + $pval{join '', @{$prop{$_}}} = 0.01; + } elsif ($x == 3) { # Queen. + push @{$prop{$_}}, ($player, 'q', 0); + $pval{join '', @{$prop{$_}}} = 0.1; + } elsif ($x == 4) { # King. + push @{$prop{$_}}, ($player, 'k', 0); + $pval{join '', @{$prop{$_}}} = '1'; # Instead of skipping if the allied king is taken in a branch, we can assign infinite value to the king. That doesn't work well with premature calculations, though, so we assign it (more than) the combined value of all other allied pieces at this point. + } else { # Bishop. + push @{$prop{$_}}, ($player, 'b', $x % 2); + $pval{join '', @{$prop{$_}}} = 0.01; + } +# } else { # Restore a previous state. + +# } + if (exists($prop{$_})) {$default_iboard[$y][$x] = join '', @{$prop{$_}}} + } + $players = 1; # Could do something with this if it weren't for @not_player... +} + +sub INIT_KEYS { # For sorted lookup of piece source. + @keys = sort { (join '', @{$prop{$a}}) cmp (join '', @{$prop{$b}}) } keys %prop; # Sort hash keys by piece properties (values). Will complain if not used at the start of the match. +} + +sub MOVEMENT_TREE { # Assume relative movement to support abritrary depth (0 < $depth < Inf). + my ($player, $depth, $i_al, $i) = (@_[0, 1], $_[5] // $_[0]*16-1, $_[2] // -4); # Support for travelling to different tree depths every player turn (could be used to create, e.g., adaptive AI). + $i += 4; + ALLY_SOURCE: foreach my $asrc (&KEYS($player)) { + my $dpval = $_[3] // 0; # Default piece value. + $i_al++; + next unless defined($asrc); + @{$tree[$i]{$asrc}} = &CHOICE($asrc); # The tree depth is $i+1. + for (my $c = $#{$tree[$i]{$asrc}}; $c >= 1; $c--) { # This should make the subroutine multiple times faster if there's no previous untravelled branch. + $keys[$i_al] = $tree[$i]{$asrc}[$c]; + $sth1->execute(@keys); + my $ditet = $sth1->fetchall_arrayref(); + if ($#$ditet != -1 and defined(${@$ditet[0]}[2/($player+1)+1])) { + {no warnings; $tmpalg{join ',', @keys} = ${@$ditet[0]}[2/($player+1)+1]}; + if ($player == $user_mode and (join '', @{$prop{$asrc}}) eq $_[7] and $_[8] eq $tree[$i]{$asrc}[$c] || $_[8] eq (join '', $prop{$tree[$i]{$asrc}[$c]})) {$tmpalg{join ',', @keys} = 'Inf'; $sth9->execute($_[9], ${@$ditet[0]}[0], ${@$ditet[0]}[1])} + $keys[$i_al] = $asrc; + pop @{$tree[$i]{$asrc}}; + } else { + $keys[$i_al] = $asrc; + last; + } + } + ALLY_DESTINATION: foreach my $adest (@{$tree[$i]{$asrc}}) { + my ($selection, @asrc, @adest); + if ($adest != $asrc) { + $keys[$i_al] = $adest; + {no warnings; $selection = join ',', @keys}; # CSV. + $sth1->execute(@keys); + my $ditet = $sth1->fetchall_arrayref(); + if ($#$ditet != -1 and defined(${@$ditet[0]}[2/($player+1)+1])) { # Already calculated the context for this $adest (and since @keys has a fixed order, for this $piece): Skip to save precious time. + $tmpalg{$selection} = ${@$ditet[0]}[2/($player+1)+1]; + $keys[$i_al] = $asrc; # Undo the (reverse-lookup) move. + next ALLY_DESTINATION; # Already stored this move in the DB, so there's no reason to recalculate our priorities now. + } #else {print 'false', "\n"} + if ($prop{$adest}) { + @adest = @{$prop{$adest}}; + $tmpalg{$selection} += $pval{join '', @adest}; # Prioritize high-value enemy pieces. + } + @{$prop{$adest}} = @asrc = @{$prop{$asrc}}; + undef $prop{$asrc}; + ($tmpalg2{$selection}, $tmpalg3{$selection}, $tmpalg4{$selection}) = (0, 0, 0); + } elsif ($#{$tree[$i]{$asrc}} <= 0) { +# my $sth = $dbh->prepare("SELECT priority FROM main_table WHERE selection = 'join ',', @keys'"); +# $sth->execute(); +# my $priority = $sth->fetchall_arrayref(); +# if (@$priority[0]) { # $asrc exists as part of @keys in the DB (as opposed to $adest). +# $keys[$i_al] = $asrc; # Undo the (reverse-lookup) move. +# next ALLY_SOURCE; # At this point we have stored every move (for this piece) in the DB, so there's no reason to go to the next ALLY_DESTINATION. +# } + next; + } + my $i_en = $_[6] // 16-$player*16-1; + ENEMY_SOURCE: foreach my $esrc (my @esrc_keys = &KEYS($not_player[$player])) { + last if $depth == 1+$i; + $i_en++; + next unless defined($esrc); +# if ($esrc != $adest) { + @{$tree[1+$i]{$esrc}} = &CHOICE($esrc); +# } #else { +# next; +# } + ENEMY_DESTINATION: foreach my $edest (@{$tree[1+$i]{$esrc}}) { + my (@esrc, @edest); + if ($#{$tree[1+$i]{$esrc}} > 0) { + $keys[$i_en] = $edest; + if ($prop{$edest}) { # Enemy dest. is defined (can either mean enemy moves to [ally || itself and ally does not move to itself]). + @edest = @{$prop{$edest}}; + if ($edest != $esrc) { + if (defined($selection)) { + if ($prop{$esrc}[1] eq 'b' || $prop{$esrc}[1] eq 'q' || $prop{$esrc}[1] eq 'r') { # Blockable "ranged" enemy pieces. Encourage other pieces to protect each other, depending on piece value. +# $tmpalg2{$selection} = $pval{join '', @edest} if $tmpalg2{$selection} < $pval{join '', @edest}; # Discourage movement by the value of the targeted ally. + my $dd = sprintf '%.0f', (sqrt(($edest - $esrc)**2)*10); # dd = (defensive) dx. Rounded because of inaccurate floats. + if ($esrc > $edest) { + $smaleer = $edest*10; + } else { + $smaleer = $esrc*10; + } + if ($dd % 11 == 0) { # NE or SW movement + for (my $bdki = $smaleer+11; $dd >= $bdki; $bdki += 11) { + $tmpalg{$selection} += $pval{join '', @edest} - $pval{join '', @asrc} if (int(join '', split(/\./, $adest)) == $bdki); + } + } elsif ($dd % 9 == 0) { # NW or SE movement + for (my $bdki = $smaleer+9; $dd >= $bdki; $bdki += 9) { + $tmpalg{$selection} += $pval{join '', @edest} - $pval{join '', @asrc} if (int(join '', split(/\./, $adest)) == $bdki); + } + } elsif ($dd % 10 == 0) { # E or W movement + for (my $bdki = $smaleer+10; $dd >= $bdki; $bdki += 10) { + $tmpalg{$selection} += $pval{join '', @edest} - $pval{join '', @asrc} if (int(join '', split(/\./, $adest)) == $bdki); + } + } elsif ($dd % 1 == 0) { # N or S movement + for (my $bdki = $smaleer+1; $dd >= $bdki; $bdki += 1) { + $tmpalg{$selection} += $pval{join '', @edest} - $pval{join '', @asrc} if (int(join '', split(/\./, $adest)) == $bdki); + } + } + } #else { + $tmpalg{$selection} -= $pval{join '', @edest}; # Not to an(other) enemy destination. + #} + } else { + $dpval = $pval{join '', @edest} if $dpval < $pval{join '', @edest}; # Encourage all movement of this piece to wherever, but (see above)... + } + } + } + @{$prop{$edest}} = @esrc = @{$prop{$esrc}}; + undef $prop{$esrc}; +# print @{$prop{$edest}}, ': ', $edest, "\n"; + } else { + next; + } + ALLY_SOURCE2: foreach my $asrc2 (my @asrc2_keys = &KEYS($player)) { + last if $depth == 2+$i; + my $dpval2 = $_[4] // 0; # Default piece value. +# if ($asrc2 != $edest) { + next unless defined($asrc2); + @{$tree[2+$i]{$asrc2}} = &CHOICE($asrc2); +# } else { +# next; +# } + foreach my $adest2 (@{$tree[2+$i]{$asrc2}}) { + next if $asrc2 == $asrc; # Skip dups as a result of looping over one of the same ally piece for every other ally piece. + my (@asrc2, @adest2); + if ($adest2 != $asrc2) { + if ($prop{$adest2}) { + @adest2 = @{$prop{$adest2}}; + if (defined($selection)) { + push @{$tmpalg3{$selection}}, $pval{join '', @adest2}; # For use in ENEMY_SOURCE2. + } +# print @{$prop{$adest2}}, ': ', @{$prop{$asrc2}}, ' ', $asrc2, ' -> ', $adest2, "\n"; +# $tmpalg3{$edest}{$adest2}++; +# print @{$prop{$adest}}, ': ', $asrc2, ' -> ', @adest2, "\n" if (scalar keys %{$tmpalg3{$asrc2}}) >= ($#{$tree[1+$i]{$esrc}}+1); # Prioritize high-value enemy pieces. +#TODO: Can't we just make a counter and decrement tmpalg if the counter > tmpalg2? +# print $adest, ' ', $adest2, ' ', @{$prop{$adest2}}, ' ', $tmpalg2{$adest}{join '', @adest2}, '/', $#{$tree[1+$i]{$esrc}}+1, "\n" and +# $tmpalg{$selection} += $pval{join '', @adest2} if $tmpalg2{$adest}{join '', @adest2} >= ($#{$tree[1+$i]{$esrc}}+1+$#esrc_keys+$#asrc2_keys); # Prioritize high-value enemy pieces. + } + @{$prop{$adest2}} = @asrc2 = @{$prop{$asrc2}}; + undef $prop{$asrc2}; +# print @{$prop{$adest2}}, ': ', $adest2, "\n"; + } elsif ($#{$tree[2+$i]{$asrc2}} <= 0) { + next; + } + ENEMY_SOURCE2: foreach my $esrc2 (&KEYS($not_player[$player])) { + last if $depth == 3+$i; +# if ($esrc2 != $adest2) { + next unless defined($esrc2); + $keys[$i_al] = $adest2; + @{$tree[3+$i]{$esrc2}} = &CHOICE($esrc2); +# } else { +# next; +# } + foreach my $edest2 (@{$tree[3+$i]{$esrc2}}) { + my (@esrc2, @edest2); + if ($#{$tree[3+$i]{$esrc2}} > 0) { + $keys[$i_en] = $edest2; + if ($prop{$edest2}) { + @edest2 = @{$prop{$edest2}}; + push @{$tmpalg3{$selection}[-1]}, $pval{join '', @edest2}; +# $tmpalg3{$selection} = 0 if $edest2 == $adest2 and $edest2 != $edest and defined($selection); +# if ($edest2 != $esrc2) { +# if ($selection) { +# if ($prop{$esrc2}[1] eq 'b' || $prop{$esrc2}[1] eq 'q' || $prop{$esrc2}[1] eq 'r') { # Blockable "ranged" enemy pieces. Encourage other pieces to protect each other, depending on piece value. +# $tmpalg4{$selection} = $pval{join '', @edest2} if $tmpalg4{$selection} < $pval{join '', @edest2}; # Discourage movement by the value of the targeted ally. +# my $dd = sprintf '%.0f', (sqrt(($edest2 - $esrc2)**2)*10); # dd = (defensive) dx. Rounded because of inaccurate floats. +# if ($esrc2 > $edest2) { +# $smaleer = $edest2*10; +# } else { +# $smaleer = $esrc2*10; +# } +# if ($dd % 11 == 0) { # NE or SW movement +# for (my $bdki = $smaleer+11; $dd >= $bdki; $bdki += 11) { +# $tmpalg3{$selection} += $pval{join '', @edest2} if (int(join '', split(/\./, $adest)) == $bdki); +# } +# } elsif ($dd % 9 == 0) { # NW or SE movement +# for (my $bdki = $smaleer+9; $dd >= $bdki; $bdki += 9) { +# $tmpalg3{$selection} += $pval{join '', @edest2} if (int(join '', split(/\./, $adest)) == $bdki); +# } +# } elsif ($dd % 10 == 0) { # E or W movement +# for (my $bdki = $smaleer+10; $dd >= $bdki; $bdki += 10) { +# $tmpalg3{$selection} += $pval{join '', @edest2} if (int(join '', split(/\./, $adest)) == $bdki); +# } +# } elsif ($dd % 1 == 0) { # N or S movement +# for (my $bdki = $smaleer+1; $dd >= $bdki; $bdki += 1) { +# $tmpalg3{$selection} += $pval{join '', @edest2} if (int(join '', split(/\./, $adest)) == $bdki); +# } +# } +# } else { +# $tmpalg3{$selection} -= $pval{join '', @edest2} + $dpval; # Not to an(other) enemy destination. +# } +# } else { +# $dpval = $pval{join '', @edest2} if $dpval < $pval{join '', @edest2}; # Encourage all movement of this piece to wherever, but (see above)... +# } +# } + } + @{$prop{$edest2}} = @esrc2 = @{$prop{$esrc2}}; + undef $prop{$esrc2}; +# print @{$prop{$edest2}}, ': ', $edest2, "\n"; + } else { + next; + } + + &MOVEMENT_TREE($player, $depth, $i, $dpval, $dpval2, $i_al, $i_en) if $depth > 4+$i; # Recursion up to $depth/4. #TODO: Make recursion give the proper amount of possibilities. + + if (@esrc2) { + if (@edest2) { + @{$prop{$edest2}} = @edest2; + } else { + undef $prop{$edest2}; + } + @{$prop{$esrc2}} = @esrc2; + } + $keys[$i_en] = $edest; + } + } + if (@asrc2) { + if (@adest2) { + @{$prop{$adest2}} = @adest2; + } else { + undef $prop{$adest2}; + } + @{$prop{$asrc2}} = @asrc2; + } + $tmpalg{$selection} += $dpval2 if $selection; + $keys[$i_al] = $adest; + } + } + if (@esrc) { + if (@edest) { + @{$prop{$edest}} = @edest; + } else { + undef $prop{$edest}; + } + @{$prop{$esrc}} = @esrc; + } + $keys[$i_en] = $esrc; + } + } + if (@asrc) { + if (@adest) { + @{$prop{$adest}} = @adest; + } else { + undef $prop{$adest}; + } + @{$prop{$asrc}} = @asrc; + } + if ($selection) { + my ($bid, $wid); + $tmpalg{$selection} += $dpval - $tmpalg2{$selection} + $tmpalg3{$selection} - $tmpalg4{$selection}; + +$sth6->execute(@keys[0..15]); +$wid = $sth6->fetchall_arrayref(); + unless ($#$wid != -1) { +$sth2->execute(@keys[0..15]); +$wid = $dbh->last_insert_id(undef, undef, undef, undef, {sequence => 'seq_wid'}); +} else {$wid = ${@$wid[0]}[0]} +$sth7->execute(@keys[16..31]); +$bid = $sth7->fetchall_arrayref(); + unless ($#$bid != -1) { +$sth3->execute(@keys[16..31]); +$bid = $dbh->last_insert_id(undef, undef, undef, undef, {sequence => 'seq_bid'}); +} else {$bid = ${@$bid[0]}[0]} + + if ($player == 0) { +$sth5->execute($bid, $wid, undef, $tmpalg{$selection}); +} else { + +#$sth7->execute(@keys[16..31]); +#my $bid = $sth7->fetchall_arrayref(); +# unless ($#$bid != -1) { +#$sth3->execute(@keys[16..31]); +#$bid = $dbh->last_insert_id(undef, undef, undef, undef, {sequence => 'seq_bid'}); +#} else {$bid = ${@$bid[0]}[0]} +#$sth6->execute(@keys[0..15]); +#my $wid = $sth6->fetchall_arrayref(); +# unless ($#$wid != -1) { +#$sth2->execute(@keys[0..15]); +#$wid = $dbh->last_insert_id(undef, undef, undef, undef, {sequence => 'seq_wid'}); +#} else {$wid = ${@$wid[0]}[0]} +$sth5->execute($bid, $wid, $tmpalg{$selection}, undef); + + } + if ($player == $user_mode and (join '', @asrc) eq $_[7] and $_[8] eq $adest || $_[8] eq (join '', @adest)) {$tmpalg{$selection} = 'Inf'; $sth9->execute($_[9], $bid, $wid)} + $keys[$i_al] = $asrc; + } + } + } +} + +sub QUEEN { + my ($pos, @out_int, $movx, $movy) = $_[0]; + my ($xpos, $ypos) = split /\./, ($out_int[0] = $pos); + foreach my $mod (0..7) { # There are eight directions from the position of the queen. + my $xmod = $direction[$mod*2]; + my $ymod = $direction[$mod*2+1]; + foreach (1..7) { # Movement (delta) cannot be lower than 1 and higher than 7. + $movx = $xpos-$_*$xmod; + $movy = $ypos-$_*$ymod; + my $mov = $movx.'.'.$movy; + if ($prop{$mov}) { + push @out_int, $mov if $prop{$mov}[0] != $prop{$_[0]}[0]; + last; + } elsif (7 >= $movx >= 0 and 7 >= $movy >= 0) { + push @out_int, $mov; + } else { + last; + } + } + } + return @out_int; +} + +sub KING { + my ($pos, @out_int, $movx, $movy) = $_[0]; + my ($xpos, $ypos) = split /\./, ($out_int[0] = $pos); + foreach my $mod (0..7) { # Eight potential directions. + my $xmod = $direction[$mod*2]; + my $ymod = $direction[$mod*2+1]; + $movx = $xpos-1*$xmod; + $movy = $ypos-1*$ymod; + my $mov = $movx.'.'.$movy; + if ($prop{$mov}) { + push @out_int, $mov if $prop{$mov}[0] != $prop{$_[0]}[0]; + } elsif (7 >= $movx >= 0 and 7 >= $movy >= 0) { + push @out_int, $mov; + } + } + return @out_int; +} + +sub PAWN { + my ($pos, @out_int, $mov, $mod) = $_[0]; + my ($xpos, $ypos) = split /\./, ($out_int[0] = $pos); + if ($prop{$_[0]}[0] == 0) { + $mod = -1; + } else { + $mod = 1; + } + if ($ypos == 1 or $ypos == 6) { + foreach (1..2) { + $mov = $xpos.'.'.($ypos-$_*$mod); + if ($prop{$mov}) { + last; + } elsif (0 <= $ypos-$_*$mod <= 7) { + push @out_int, $mov; + } + } + } else { + $mov = $xpos.'.'.($ypos-1*$mod); + unless ($prop{$mov}) { + push @out_int, $mov if 0 <= $ypos-1*$mod <= 7; + } + } + $mov = ($xpos-1*$mod).'.'.($ypos-1*$mod); + if ($prop{$mov}) { + push @out_int, $mov if $prop{$mov}[0] != $prop{$_[0]}[0]; + } + $mov = ($xpos+1*$mod).'.'.($ypos-1*$mod); + if ($prop{$mov}) { + push @out_int, $mov if $prop{$mov}[0] != $prop{$_[0]}[0]; + } + return @out_int; +} + +sub BISHOP { + my ($pos, @out_int, $movx, $movy) = $_[0]; + my ($xpos, $ypos) = split /\./, ($out_int[0] = $pos); + foreach my $mod (0..3) { # Four potential diagonal directions. + my $xmod = $direction[$mod*2]; + my $ymod = $direction[$mod*2+1]; + foreach (1..7) { + $movx = $xpos-$_*$xmod; + $movy = $ypos-$_*$ymod; + my $mov = $movx.'.'.$movy; + if ($prop{$mov}) { + push @out_int, $mov if $prop{$mov}[0] != $prop{$_[0]}[0]; + last; + } elsif (7 >= $movx >= 0 and 7 >= $movy >= 0) { + push @out_int, $mov; + } else { + last; + } + } + } + return @out_int; +} + +sub ROOK { + my ($pos, @out_int, $movx, $movy) = $_[0]; + my ($xpos, $ypos) = split /\./, ($out_int[0] = $pos); + foreach my $mod (4..7) { # Four potential straight directions. + my $xmod = $direction[$mod*2]; + my $ymod = $direction[$mod*2+1]; + foreach (1..7) { + $movx = $xpos-$_*$xmod; + $movy = $ypos-$_*$ymod; + my $mov = $movx.'.'.$movy; + if ($prop{$mov}) { + push @out_int, $mov if $prop{$mov}[0] != $prop{$_[0]}[0]; + last; + } elsif (7 >= $movx >= 0 and 7 >= $movy >= 0) { + push @out_int, $mov; + } else { + last; + } + } + } + return @out_int; +} + +sub KNIGHT { + my ($pos, @out_int, $movx, $movy) = $_[0]; + my ($xpos, $ypos) = split /\./, ($out_int[0] = $pos); + foreach my $mod (0..3,8..11) { # Eight potential directions. + my $xmod = $direction[$mod*2]; + my $ymod = $direction[$mod*2+1]; + $movx = $xpos-2*$xmod; + $movy = $ypos-1*$ymod; + my $mov = $movx.'.'.$movy; + if ($prop{$mov}) { + push @out_int, $mov if $prop{$mov}[0] != $prop{$_[0]}[0]; + } elsif (7 >= $movx >= 0 and 7 >= $movy >= 0) { + push @out_int, $mov; + } + } + return @out_int; +} + +sub CHOICE { # Strict refs compliance. + if ($prop{$_[0]}[1] eq 'p') { + &PAWN($_[0]); + } elsif ($prop{$_[0]}[1] eq 'n') { + &KNIGHT($_[0]); + } elsif ($prop{$_[0]}[1] eq 'b') { + &BISHOP($_[0]); + } elsif ($prop{$_[0]}[1] eq 'r') { + &ROOK($_[0]); + } elsif ($prop{$_[0]}[1] eq 'q') { + &QUEEN($_[0]); + } elsif ($prop{$_[0]}[1] eq 'k') { + &KING($_[0]); + } else { + die 'Invalid parameter(s): ', @_, "\n"; + } +} + +sub KEYS { # Arguments: ($player). + my ($player, @tree_keys) = $_[0]; + map {if (defined($_)) {push @tree_keys, $_ if $prop{$_}} else {push @tree_keys, undef}} @keys[$player*16..$player*16+15]; + return @tree_keys; +} + +sub CLEANUP_POSTGAME { + undef %prop; + $#keys = -1; +} + +sub CLEANUP_POSTTURN { + undef %tmpalg; + undef %tmpalg2; + $#tree = -1; +} + + +sub POSTCHESS_CALC { +my ($pval, $called_player, $reason) = @_; # Arguments: (Value of all pieces of $player - $not_player[$player], $player, reason for exiting the game (did a $player win?)). + foreach my $current_player (@player) { + my $mpval; + my $sth4 = $dbh->prepare(q/UPDATE context SET /.$pplayer[$not_player[$current_player]].q/prio = ? FROM black, white WHERE black.id = bid and white.id = wid and white.b0 = ? and white.b1 = ? and white.k0 = ? and white.n0 = ? and white.n1 = ? and white.p0 = ? and white.p1 = ? and white.p2 = ? and white.p3 = ? and white.p4 = ? and white.p5 = ? and white.p6 = ? and white.p7 = ? and white.q0 = ? and white.r0 = ? and white.r1 = ? and black.b0 = ? and black.b1 = ? and black.k0 = ? and black.n0 = ? and black.n1 = ? and black.p0 = ? and black.p1 = ? and black.p2 = ? and black.p3 = ? and black.p4 = ? and black.p5 = ? and black.p6 = ? and black.p7 = ? and black.q0 = ? and black.r0 = ? and black.r1 = ?/); + if ($reason == 0) { # Stalemate. Various causes. + if ($current_player == 0) { + $mpval = -1; # Try out other selections (if the next game is similar) for benefit of player 1. #TODO: Remove in production. + } elsif ($called_player == 0) { + $mpval = $pval * -1; + } else { + $mpval = $pval; + } + } elsif ($reason == 1) { + if ($current_player == 0) { + if ($called_player == 0) { + $mpval = $pval; + } else { + $mpval = $pval * -1; + } + } else { + if ($called_player == 1) { + $mpval = $pval; + } else { + $mpval = $pval * -1; + } + } + } + foreach my $anothervar (keys %{$what_i_did[$current_player]}) { + $what_i_did[$current_player]{$anothervar} += $mpval; + $sth4->execute($what_i_did[$current_player]{$anothervar}, @keys); + } + } +} + +sub PROGRAM { +my $sessid = $_[2]{'id'}; +$user_mode = 0; +# if (!defined($user_mode)) { +# print 'Please input your side:', "\n"; +# foreach (@player) { +# print $_, ': '; +# if ($_ == 0) { +# print 'white (recommended)', "\n"; # The AI has been trained for the opponent (you) making the first move. Reflect that in the selection for now. +# } elsif ($_ == 1) { +# print 'black', "\n"; +# } +# } +# INPUT_LOOP: while (1) { +# chomp(my $input = ); +# foreach my $player (@player) { +# if ($input eq $player) { +# $user_mode = $player; +# last INPUT_LOOP; +# } +# } +# print 'Invalid input', ' `', $input, '`', ".\n"; +# } +# } + +# MATCH: while (1) { + my %diff; + $player_turn++; +# $player = ($player_turn+1) % 2; + + TURN: foreach my $player (@player) { +# @{$diff{'msg'}{'turn'}}[$player] = 'Player ' . $player . ' turn ' . $player_turn . ':'; + push @{$diff{$pplayer[$player]}{'status'}}, $player_turn; + my ($depth, %key_list_by_value, $prio, $ice, @selection); + + my ($dpval, $i_al) = (0, 0); + if ($player == $user_mode) { # If the player is human-controlled, we needn't more than $depth 1 (for input validation). + $depth = 1; + &MOVEMENT_TREE($player, $depth, undef, undef, undef, undef, undef, $_[0], $_[1], $sessid); + } else { + $depth = 2; # Usually about 20^$depth possibilities (but ten times as much iterates for including no movement). + &MOVEMENT_TREE($player, $depth); + } + foreach (keys %tmpalg) { + my $val = $tmpalg{$_}; + push @{$key_list_by_value{$val}}, $_; + unless (defined($prio)) { + $prio = $val; + } + if ($val > $prio) { + $prio = $val; + } + } + if ($player == $user_mode && $prio != 'Inf') { # Invalid user input. + $player_turn--; +# push @{$diff{$player}{'warn'}} = 'Reverting an invalid set.'; + undef $diff{$pplayer[$not_player[$player]]}; + push @{$diff{$pplayer[$player]}{'status'}}, 0; +# redo TURN; + return %diff; + } + + if (scalar keys %key_list_by_value > 0) { + for (my $ii = 0; $#{$key_list_by_value{$prio}} >= $ii; $ii++) { + $selection[$ii] = $key_list_by_value{$prio}[$ii]; + } + $ice = int(rand($#selection+1)); + } elsif ($user_mode != $player) { # The other side has checkmated you (the AI). The AI should know when to give up (even if it weren't for efficiency reasons). +# @{$diff{'msg'}{'gstatus'}}[$player] = 'Player ' . $player . ' resigns!'; + push @{$diff{$pplayer[$player]}{'status'}}, 5; + if ($user_mode == -1) { # So, instead of performing winning moves (which will always be done at this tree depth), we have enough data here to revert back to some previous (hence valid) board state (with untravelled nodes). Rather than starting from scratch every time, this might be preferable for AI training. The importance of the first few chess moves shouldn't be undermined, however. Therefore, include some appropriate randomization. + #TODO: Usual DB writing followed by POC. + next TURN; + } else { + next TURN; + } + } + + my $matches = grep {!/^[01][.]k[.]0_/} keys %tmpalg; # When only the king can move... + if ($matches == 0) { + $counter++; + if ($counter >= 2 && $player_turn > 24) { # End the game if the same applies to the opponent (only the king can move), and $player_turn have passed. +# @{$diff{'msg'}{'gstatus'}}[$player] = 'Only the kings can act. Stalemate...'; + push @{$diff{$pplayer[$player]}{'status'}}, 4; + &POSTCHESS_CALC(&PRETTY_CALC(0, $player), 0); +# return; + } + } + + if ($player_turn >= $action_limit) { # TODO: Is this needed when we have @pseudoinfinite_loop_check? +# @{$diff{'msg'}{'gstatus'}}[$player] = 'Total turn limit ' . ($player_turn*2) . ' reached: Stalemate...'; + push @{$diff{$pplayer[$player]}{'status'}}, 3; + &POSTCHESS_CALC(&PRETTY_CALC(0, $player), 0); +# return; + } + + if (($player_turn*2+$player) % ($loop_limit+1) == 0) { # When player 0 is iterating through all chess possibilities in training mode, stop & do the usual decrement when both players have been doing the same four-turn loop at least three times successively. If we don't stop the program here but do stop the four-turn loop, player 1 might prioritize creating loops when breaking the loop would be a final blow for player 0. TODO: Alternatively, we might revert back here to some previous state... + my ($evenval1, $unevenval1, $evenval2, $unevenval2); + for (my $counter3 = 0; $#pseudoinfinite_loop_check >= $counter3; $counter3++) { + if ($counter3 > 1) { + if ($counter3 > 3) { + if ($counter3 % 2 == 0) { + if ($counter3 % 4 == 0) { + next if $evenval1 eq $pseudoinfinite_loop_check[$counter3]; + last; + } elsif (($counter3+1) % 4 == 0) { + next if $unevenval1 eq $pseudoinfinite_loop_check[$counter3]; + last; + } elsif (($counter3+2) % 4 == 0) { + next if $evenval2 eq $pseudoinfinite_loop_check[$counter3]; + last; + } elsif (($counter3+3) % 4 == 0) { + next if $unevenval2 eq $pseudoinfinite_loop_check[$counter3]; + last; + } + } + } elsif ($counter3 % 2 == 0) { + $evenval2 = $pseudoinfinite_loop_check[$counter3]; + next; + } else { + $unevenval2 = $pseudoinfinite_loop_check[$counter3]; + next; + } + } elsif ($counter3 % 2 == 0) { + $evenval1 = $pseudoinfinite_loop_check[$counter3]; + next; + } else { + $unevenval1 = $pseudoinfinite_loop_check[$counter3]; + next; + } +# @{$diff{'status'}}[$player] = 'Loop limit ' . $loop_limit . ' reached: Stalemate...'; + push @{$diff{$pplayer[$player]}{'status'}}, 2; + &POSTCHESS_CALC(&PRETTY_CALC(0, $player), 0); +# return; + } + undef @pseudoinfinite_loop_check; + } + push @pseudoinfinite_loop_check, $selection[$ice]; + + push @{$diff{$pplayer[$player]}{'prio'}}, $prio; + push @{$diff{$pplayer[$player]}{'moveno'}}, ($ice+1) . '/' . ($#selection+1); +# @{$diff{'msg'}{'verbose'}}[$player] = $selection[$ice]; + + $what_i_did[$player]{$selection[$ice]} = $prio; + my $c = 0; + my $adest; + foreach (split /,/, $selection[$ice]) { + if (defined($keys[$c]) and $keys[$c] != $_) { + $adest = $_; + last; + } + $c++; + } + my $asrc = $keys[$c]; + my $piece = $prop{$asrc}; + push @{$diff{$pplayer[$player]}{'src'}}, $asrc; + push @{$diff{$pplayer[$player]}{'src'}}, join '', @{$piece}; + push @{$diff{$pplayer[$player]}{'dst'}}, $adest; +# @{$diff{$player}{'move'}}[$player*2] = (join '', @{$piece}) . ' moves from ' . $asrc . ' to ' . $adest; + if (defined($prop{$adest})) { + push @{$diff{$pplayer[$player]}{'dst'}}, (join '', @{$prop{$adest}}); +# push @{$diff{[$player]}{'move'}} = ' and takes ' . (join '', @{$prop{$adest}}) . '!'; + if ($prop{$adest}[1] eq 'k') { + push @{$diff{$pplayer[$player]}{'status'}}, 1; +# push @{$diff{[$player]}{'win'}}, ' Player ' . $player . ' wins!'; + &POSTCHESS_CALC(&PRETTY_CALC(0, $player), 1); +# return; + } + for (my $c = 0; $#keys >= $c; $c++){$keys[$c] = undef and last if defined($keys[$c]) and $keys[$c] == $adest} + @{$prop{$adest}} = @{$piece}; + $keys[$c] = $adest; + undef $prop{$asrc}; + } else { + @{$prop{$adest}} = @{$piece}; + $keys[$c] = $adest; + undef $prop{$asrc}; + } +# &PRETTY_CALC; + &CLEANUP_POSTTURN; + } +#exit; +# } + return %diff +} + +#&CLEANUP_POSTGAME; + &INIT_BOARD; + &INIT_KEYS; + +get '/move/:src/:dst' => sub { +if (session('init')) { + my %diff = &PROGRAM(route_parameters->get('src'), route_parameters->get('dst'), session); # Includes player input. + encode_json(\%diff); +} +}; + +any ['get', 'post'] => '/' => sub { + if (request->method() eq "POST") { +if (session('init')) { + if (length(body_parameters->get('id')) == 1 and body_parameters->get('id') =~ m/\A[1-7]\z/) { # Sanitize user input (even if in a session). + my $setting_id = body_parameters->get('id'); + redirect '/aaaaa'; + } +} + } else { +if (session('init')) { + $sth8->execute(session('id')); + template 'index' => {board => $sth8->fetchall_arrayref()}; +} else { + session 'init' => true; + template 'index' => {board => \@default_iboard}; +} + } +}; + +true; diff --git a/chess_gui/public/404.html b/chess_gui/public/404.html new file mode 100644 index 0000000..c2f4032 --- /dev/null +++ b/chess_gui/public/404.html @@ -0,0 +1,18 @@ + + + + + + Error 404 + + + +

Error 404

+
+

Page Not Found

Sorry, this is the void.

+
+ + + diff --git a/chess_gui/public/500.html b/chess_gui/public/500.html new file mode 100644 index 0000000..d84ebbc --- /dev/null +++ b/chess_gui/public/500.html @@ -0,0 +1,18 @@ + + + + + + Error 500 + + + +

Error 500

+
+

Internal Server Error

Wooops, something went wrong

+
+ + + diff --git a/chess_gui/public/css/error.css b/chess_gui/public/css/error.css new file mode 100644 index 0000000..a39e596 --- /dev/null +++ b/chess_gui/public/css/error.css @@ -0,0 +1,86 @@ +body { + font-family: Lucida,sans-serif; +} + +h1 { + color: #AA0000; + border-bottom: 1px solid #444; +} + +h2 { color: #444; } + +pre { + font-family: "lucida console","monaco","andale mono","bitstream vera sans mono","consolas",monospace; + font-size: 12px; + border-left: 2px solid #777; + padding-left: 1em; +} + +footer { + font-size: 10px; +} + +span.key { + color: #449; + font-weight: bold; + width: 120px; + display: inline; +} + +span.value { + color: #494; +} + +/* these are for the message boxes */ + +pre.content { + background-color: #eee; + color: #000; + padding: 1em; + margin: 0; + border: 1px solid #aaa; + border-top: 0; + margin-bottom: 1em; + overflow-x: auto; +} + +div.title { + font-family: "lucida console","monaco","andale mono","bitstream vera sans mono","consolas",monospace; + font-size: 12px; + background-color: #aaa; + color: #444; + font-weight: bold; + padding: 3px; + padding-left: 10px; +} + +table.context { + border-spacing: 0; +} + +table.context th, table.context td { + padding: 0; +} + +table.context th { + color: #889; + font-weight: normal; + padding-right: 15px; + text-align: right; +} + +.errline { + color: red; +} + +pre.error { + background: #334; + color: #ccd; + padding: 1em; + border-top: 1px solid #000; + border-left: 1px solid #000; + border-right: 1px solid #eee; + border-bottom: 1px solid #eee; + overflow-x: auto; +} + diff --git a/chess_gui/public/css/index.css b/chess_gui/public/css/index.css new file mode 100644 index 0000000..72bf2f0 --- /dev/null +++ b/chess_gui/public/css/index.css @@ -0,0 +1,63 @@ +a { + display: block; + text-decoration: none; + outline-style: solid; + color: white; + background-image: url(i/tem.png); +} + +ol > li li { + display: inline-block; + width: 32px; +} + +#y-co { + display: flex; + flex-flow: column-reverse; + width: max-content; +} + +#x-co { + display: inline-flex; + flex-flow: row; + width: max-content; + margin-top: 32px; +} + +.x-co { + display: inline-block; + text-align: center; + width: 32px; +} + +.features, .keys, .values { + list-style-type: none; + padding: 0; + margin: 0; +} + +.features { + display: grid; +} + +.key { + display: none; +} + +.key .values { + display: none; +} + +h3 > ul:hover .key { + display: inline-block; +} + +.key:hover .values { + display: flex; + flex-flow: column; + position: fixed; +} + +/*img {*/ +/* position: relative;*/ +/*}*/ diff --git a/chess_gui/public/dispatch.cgi b/chess_gui/public/dispatch.cgi new file mode 100755 index 0000000..706ba0c --- /dev/null +++ b/chess_gui/public/dispatch.cgi @@ -0,0 +1,16 @@ +#!/usr/bin/env perl +BEGIN { $ENV{DANCER_APPHANDLER} = 'PSGI';} +use Dancer2; +use FindBin '$RealBin'; +use Plack::Runner; + +# For some reason Apache SetEnv directives don't propagate +# correctly to the dispatchers, so forcing PSGI and env here +# is safer. +set apphandler => 'PSGI'; +set environment => 'production'; + +my $psgi = path($RealBin, '..', 'bin', 'app.psgi'); +die "Unable to read startup script: $psgi" unless -r $psgi; + +Plack::Runner->run($psgi); diff --git a/chess_gui/public/dispatch.fcgi b/chess_gui/public/dispatch.fcgi new file mode 100755 index 0000000..ad42deb --- /dev/null +++ b/chess_gui/public/dispatch.fcgi @@ -0,0 +1,18 @@ +#!/usr/bin/env perl +BEGIN { $ENV{DANCER_APPHANDLER} = 'PSGI';} +use Dancer2; +use FindBin '$RealBin'; +use Plack::Handler::FCGI; + +# For some reason Apache SetEnv directives don't propagate +# correctly to the dispatchers, so forcing PSGI and env here +# is safer. +set apphandler => 'PSGI'; +set environment => 'production'; + +my $psgi = path($RealBin, '..', 'bin', 'app.psgi'); +my $app = do($psgi); +die "Unable to read startup script: $@" if $@; +my $server = Plack::Handler::FCGI->new(nproc => 5, detach => 1); + +$server->run($app); diff --git a/chess_gui/public/i/0.0.png b/chess_gui/public/i/0.0.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/0.0.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/0.1.png b/chess_gui/public/i/0.1.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/0.1.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/0.2.png b/chess_gui/public/i/0.2.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/0.2.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/0.3.png b/chess_gui/public/i/0.3.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/0.3.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/0.4.png b/chess_gui/public/i/0.4.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/0.4.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/0.5.png b/chess_gui/public/i/0.5.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/0.5.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/0.6.png b/chess_gui/public/i/0.6.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/0.6.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/0.7.png b/chess_gui/public/i/0.7.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/0.7.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/0b0.png b/chess_gui/public/i/0b0.png new file mode 120000 index 0000000..59edee4 --- /dev/null +++ b/chess_gui/public/i/0b0.png @@ -0,0 +1 @@ +w/bishop.png \ No newline at end of file diff --git a/chess_gui/public/i/0b1.png b/chess_gui/public/i/0b1.png new file mode 120000 index 0000000..59edee4 --- /dev/null +++ b/chess_gui/public/i/0b1.png @@ -0,0 +1 @@ +w/bishop.png \ No newline at end of file diff --git a/chess_gui/public/i/0k0.png b/chess_gui/public/i/0k0.png new file mode 120000 index 0000000..535e20d --- /dev/null +++ b/chess_gui/public/i/0k0.png @@ -0,0 +1 @@ +w/king.png \ No newline at end of file diff --git a/chess_gui/public/i/0n0.png b/chess_gui/public/i/0n0.png new file mode 120000 index 0000000..dc299fe --- /dev/null +++ b/chess_gui/public/i/0n0.png @@ -0,0 +1 @@ +w/knight.png \ No newline at end of file diff --git a/chess_gui/public/i/0n1.png b/chess_gui/public/i/0n1.png new file mode 120000 index 0000000..dc299fe --- /dev/null +++ b/chess_gui/public/i/0n1.png @@ -0,0 +1 @@ +w/knight.png \ No newline at end of file diff --git a/chess_gui/public/i/0p0.png b/chess_gui/public/i/0p0.png new file mode 120000 index 0000000..380a247 --- /dev/null +++ b/chess_gui/public/i/0p0.png @@ -0,0 +1 @@ +w/pawn.png \ No newline at end of file diff --git a/chess_gui/public/i/0p1.png b/chess_gui/public/i/0p1.png new file mode 120000 index 0000000..380a247 --- /dev/null +++ b/chess_gui/public/i/0p1.png @@ -0,0 +1 @@ +w/pawn.png \ No newline at end of file diff --git a/chess_gui/public/i/0p2.png b/chess_gui/public/i/0p2.png new file mode 120000 index 0000000..380a247 --- /dev/null +++ b/chess_gui/public/i/0p2.png @@ -0,0 +1 @@ +w/pawn.png \ No newline at end of file diff --git a/chess_gui/public/i/0p3.png b/chess_gui/public/i/0p3.png new file mode 120000 index 0000000..380a247 --- /dev/null +++ b/chess_gui/public/i/0p3.png @@ -0,0 +1 @@ +w/pawn.png \ No newline at end of file diff --git a/chess_gui/public/i/0p4.png b/chess_gui/public/i/0p4.png new file mode 120000 index 0000000..380a247 --- /dev/null +++ b/chess_gui/public/i/0p4.png @@ -0,0 +1 @@ +w/pawn.png \ No newline at end of file diff --git a/chess_gui/public/i/0p5.png b/chess_gui/public/i/0p5.png new file mode 120000 index 0000000..380a247 --- /dev/null +++ b/chess_gui/public/i/0p5.png @@ -0,0 +1 @@ +w/pawn.png \ No newline at end of file diff --git a/chess_gui/public/i/0p6.png b/chess_gui/public/i/0p6.png new file mode 120000 index 0000000..380a247 --- /dev/null +++ b/chess_gui/public/i/0p6.png @@ -0,0 +1 @@ +w/pawn.png \ No newline at end of file diff --git a/chess_gui/public/i/0p7.png b/chess_gui/public/i/0p7.png new file mode 120000 index 0000000..380a247 --- /dev/null +++ b/chess_gui/public/i/0p7.png @@ -0,0 +1 @@ +w/pawn.png \ No newline at end of file diff --git a/chess_gui/public/i/0q0.png b/chess_gui/public/i/0q0.png new file mode 120000 index 0000000..0160421 --- /dev/null +++ b/chess_gui/public/i/0q0.png @@ -0,0 +1 @@ +w/queen.png \ No newline at end of file diff --git a/chess_gui/public/i/0r0.png b/chess_gui/public/i/0r0.png new file mode 120000 index 0000000..1c34e6a --- /dev/null +++ b/chess_gui/public/i/0r0.png @@ -0,0 +1 @@ +w/rook.png \ No newline at end of file diff --git a/chess_gui/public/i/0r1.png b/chess_gui/public/i/0r1.png new file mode 120000 index 0000000..1c34e6a --- /dev/null +++ b/chess_gui/public/i/0r1.png @@ -0,0 +1 @@ +w/rook.png \ No newline at end of file diff --git a/chess_gui/public/i/1.0.png b/chess_gui/public/i/1.0.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/1.0.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/1.1.png b/chess_gui/public/i/1.1.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/1.1.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/1.2.png b/chess_gui/public/i/1.2.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/1.2.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/1.3.png b/chess_gui/public/i/1.3.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/1.3.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/1.4.png b/chess_gui/public/i/1.4.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/1.4.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/1.5.png b/chess_gui/public/i/1.5.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/1.5.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/1.6.png b/chess_gui/public/i/1.6.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/1.6.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/1.7.png b/chess_gui/public/i/1.7.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/1.7.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/1b0.png b/chess_gui/public/i/1b0.png new file mode 120000 index 0000000..2b98e6e --- /dev/null +++ b/chess_gui/public/i/1b0.png @@ -0,0 +1 @@ +b/bishop.png \ No newline at end of file diff --git a/chess_gui/public/i/1b1.png b/chess_gui/public/i/1b1.png new file mode 120000 index 0000000..2b98e6e --- /dev/null +++ b/chess_gui/public/i/1b1.png @@ -0,0 +1 @@ +b/bishop.png \ No newline at end of file diff --git a/chess_gui/public/i/1k0.png b/chess_gui/public/i/1k0.png new file mode 120000 index 0000000..cfc4611 --- /dev/null +++ b/chess_gui/public/i/1k0.png @@ -0,0 +1 @@ +b/king.png \ No newline at end of file diff --git a/chess_gui/public/i/1n0.png b/chess_gui/public/i/1n0.png new file mode 120000 index 0000000..4846c1d --- /dev/null +++ b/chess_gui/public/i/1n0.png @@ -0,0 +1 @@ +b/knight.png \ No newline at end of file diff --git a/chess_gui/public/i/1n1.png b/chess_gui/public/i/1n1.png new file mode 120000 index 0000000..4846c1d --- /dev/null +++ b/chess_gui/public/i/1n1.png @@ -0,0 +1 @@ +b/knight.png \ No newline at end of file diff --git a/chess_gui/public/i/1p0.png b/chess_gui/public/i/1p0.png new file mode 120000 index 0000000..d543143 --- /dev/null +++ b/chess_gui/public/i/1p0.png @@ -0,0 +1 @@ +b/pawn.png \ No newline at end of file diff --git a/chess_gui/public/i/1p1.png b/chess_gui/public/i/1p1.png new file mode 120000 index 0000000..d543143 --- /dev/null +++ b/chess_gui/public/i/1p1.png @@ -0,0 +1 @@ +b/pawn.png \ No newline at end of file diff --git a/chess_gui/public/i/1p2.png b/chess_gui/public/i/1p2.png new file mode 120000 index 0000000..d543143 --- /dev/null +++ b/chess_gui/public/i/1p2.png @@ -0,0 +1 @@ +b/pawn.png \ No newline at end of file diff --git a/chess_gui/public/i/1p3.png b/chess_gui/public/i/1p3.png new file mode 120000 index 0000000..d543143 --- /dev/null +++ b/chess_gui/public/i/1p3.png @@ -0,0 +1 @@ +b/pawn.png \ No newline at end of file diff --git a/chess_gui/public/i/1p4.png b/chess_gui/public/i/1p4.png new file mode 120000 index 0000000..d543143 --- /dev/null +++ b/chess_gui/public/i/1p4.png @@ -0,0 +1 @@ +b/pawn.png \ No newline at end of file diff --git a/chess_gui/public/i/1p5.png b/chess_gui/public/i/1p5.png new file mode 120000 index 0000000..d543143 --- /dev/null +++ b/chess_gui/public/i/1p5.png @@ -0,0 +1 @@ +b/pawn.png \ No newline at end of file diff --git a/chess_gui/public/i/1p6.png b/chess_gui/public/i/1p6.png new file mode 120000 index 0000000..d543143 --- /dev/null +++ b/chess_gui/public/i/1p6.png @@ -0,0 +1 @@ +b/pawn.png \ No newline at end of file diff --git a/chess_gui/public/i/1p7.png b/chess_gui/public/i/1p7.png new file mode 120000 index 0000000..d543143 --- /dev/null +++ b/chess_gui/public/i/1p7.png @@ -0,0 +1 @@ +b/pawn.png \ No newline at end of file diff --git a/chess_gui/public/i/1q0.png b/chess_gui/public/i/1q0.png new file mode 120000 index 0000000..011ab63 --- /dev/null +++ b/chess_gui/public/i/1q0.png @@ -0,0 +1 @@ +b/queen.png \ No newline at end of file diff --git a/chess_gui/public/i/1r0.png b/chess_gui/public/i/1r0.png new file mode 120000 index 0000000..4a478e4 --- /dev/null +++ b/chess_gui/public/i/1r0.png @@ -0,0 +1 @@ +b/rook.png \ No newline at end of file diff --git a/chess_gui/public/i/1r1.png b/chess_gui/public/i/1r1.png new file mode 120000 index 0000000..4a478e4 --- /dev/null +++ b/chess_gui/public/i/1r1.png @@ -0,0 +1 @@ +b/rook.png \ No newline at end of file diff --git a/chess_gui/public/i/2.0.png b/chess_gui/public/i/2.0.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/2.0.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/2.1.png b/chess_gui/public/i/2.1.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/2.1.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/2.2.png b/chess_gui/public/i/2.2.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/2.2.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/2.3.png b/chess_gui/public/i/2.3.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/2.3.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/2.4.png b/chess_gui/public/i/2.4.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/2.4.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/2.5.png b/chess_gui/public/i/2.5.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/2.5.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/2.6.png b/chess_gui/public/i/2.6.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/2.6.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/2.7.png b/chess_gui/public/i/2.7.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/2.7.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/3.0.png b/chess_gui/public/i/3.0.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/3.0.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/3.1.png b/chess_gui/public/i/3.1.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/3.1.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/3.2.png b/chess_gui/public/i/3.2.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/3.2.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/3.3.png b/chess_gui/public/i/3.3.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/3.3.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/3.4.png b/chess_gui/public/i/3.4.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/3.4.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/3.5.png b/chess_gui/public/i/3.5.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/3.5.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/3.6.png b/chess_gui/public/i/3.6.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/3.6.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/3.7.png b/chess_gui/public/i/3.7.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/3.7.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/4.0.png b/chess_gui/public/i/4.0.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/4.0.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/4.1.png b/chess_gui/public/i/4.1.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/4.1.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/4.2.png b/chess_gui/public/i/4.2.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/4.2.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/4.3.png b/chess_gui/public/i/4.3.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/4.3.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/4.4.png b/chess_gui/public/i/4.4.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/4.4.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/4.5.png b/chess_gui/public/i/4.5.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/4.5.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/4.6.png b/chess_gui/public/i/4.6.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/4.6.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/4.7.png b/chess_gui/public/i/4.7.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/4.7.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/5.0.png b/chess_gui/public/i/5.0.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/5.0.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/5.1.png b/chess_gui/public/i/5.1.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/5.1.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/5.2.png b/chess_gui/public/i/5.2.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/5.2.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/5.3.png b/chess_gui/public/i/5.3.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/5.3.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/5.4.png b/chess_gui/public/i/5.4.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/5.4.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/5.5.png b/chess_gui/public/i/5.5.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/5.5.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/5.6.png b/chess_gui/public/i/5.6.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/5.6.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/5.7.png b/chess_gui/public/i/5.7.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/5.7.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/6.0.png b/chess_gui/public/i/6.0.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/6.0.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/6.1.png b/chess_gui/public/i/6.1.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/6.1.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/6.2.png b/chess_gui/public/i/6.2.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/6.2.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/6.3.png b/chess_gui/public/i/6.3.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/6.3.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/6.4.png b/chess_gui/public/i/6.4.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/6.4.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/6.5.png b/chess_gui/public/i/6.5.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/6.5.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/6.6.png b/chess_gui/public/i/6.6.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/6.6.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/6.7.png b/chess_gui/public/i/6.7.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/6.7.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/7.0.png b/chess_gui/public/i/7.0.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/7.0.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/7.1.png b/chess_gui/public/i/7.1.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/7.1.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/7.2.png b/chess_gui/public/i/7.2.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/7.2.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/7.3.png b/chess_gui/public/i/7.3.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/7.3.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/7.4.png b/chess_gui/public/i/7.4.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/7.4.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/7.5.png b/chess_gui/public/i/7.5.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/7.5.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/7.6.png b/chess_gui/public/i/7.6.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/7.6.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/7.7.png b/chess_gui/public/i/7.7.png new file mode 120000 index 0000000..d8fd813 --- /dev/null +++ b/chess_gui/public/i/7.7.png @@ -0,0 +1 @@ +dummy.gif \ No newline at end of file diff --git a/chess_gui/public/i/b/bishop.png b/chess_gui/public/i/b/bishop.png new file mode 100644 index 0000000..db5f369 Binary files /dev/null and b/chess_gui/public/i/b/bishop.png differ diff --git a/chess_gui/public/i/b/king.png b/chess_gui/public/i/b/king.png new file mode 100644 index 0000000..a3c76f1 Binary files /dev/null and b/chess_gui/public/i/b/king.png differ diff --git a/chess_gui/public/i/b/knight.png b/chess_gui/public/i/b/knight.png new file mode 100644 index 0000000..e708c40 Binary files /dev/null and b/chess_gui/public/i/b/knight.png differ diff --git a/chess_gui/public/i/b/pawn.png b/chess_gui/public/i/b/pawn.png new file mode 100644 index 0000000..d69dfa0 Binary files /dev/null and b/chess_gui/public/i/b/pawn.png differ diff --git a/chess_gui/public/i/b/queen.png b/chess_gui/public/i/b/queen.png new file mode 100644 index 0000000..050765d Binary files /dev/null and b/chess_gui/public/i/b/queen.png differ diff --git a/chess_gui/public/i/b/rook.png b/chess_gui/public/i/b/rook.png new file mode 100644 index 0000000..056b5b7 Binary files /dev/null and b/chess_gui/public/i/b/rook.png differ diff --git a/chess_gui/public/i/dummy.gif b/chess_gui/public/i/dummy.gif new file mode 100644 index 0000000..aee0fa7 Binary files /dev/null and b/chess_gui/public/i/dummy.gif differ diff --git a/chess_gui/public/i/w/bishop.png b/chess_gui/public/i/w/bishop.png new file mode 100644 index 0000000..fb51f0b Binary files /dev/null and b/chess_gui/public/i/w/bishop.png differ diff --git a/chess_gui/public/i/w/king.png b/chess_gui/public/i/w/king.png new file mode 100644 index 0000000..23c445c Binary files /dev/null and b/chess_gui/public/i/w/king.png differ diff --git a/chess_gui/public/i/w/knight.png b/chess_gui/public/i/w/knight.png new file mode 100644 index 0000000..4784c16 Binary files /dev/null and b/chess_gui/public/i/w/knight.png differ diff --git a/chess_gui/public/i/w/pawn.png b/chess_gui/public/i/w/pawn.png new file mode 100644 index 0000000..3387761 Binary files /dev/null and b/chess_gui/public/i/w/pawn.png differ diff --git a/chess_gui/public/i/w/queen.png b/chess_gui/public/i/w/queen.png new file mode 100644 index 0000000..0a75bc7 Binary files /dev/null and b/chess_gui/public/i/w/queen.png differ diff --git a/chess_gui/public/i/w/rook.png b/chess_gui/public/i/w/rook.png new file mode 100644 index 0000000..2c8d4c0 Binary files /dev/null and b/chess_gui/public/i/w/rook.png differ diff --git a/chess_gui/public/js/dand.js b/chess_gui/public/js/dand.js new file mode 100644 index 0000000..249f5a7 --- /dev/null +++ b/chess_gui/public/js/dand.js @@ -0,0 +1,44 @@ +var drag; +var drop; +var xhr = new XMLHttpRequest(); +//xhr.open('GET', 'data/move.json', true); + +for (b=0; C('coord').length > b; b++) {C('coord')[b].onmousedown = function () { +event.preventDefault(); +//drop = null; +drag = this.id; +}} + +for (b=0; C('coord').length > b; b++) {C('coord')[b].onmouseup = function () { +drop = this.id; +//if (drop !== undefined && drag !== undefined) {console.log(drag + ' -> ' + drop)} +//if (drop !== undefined && drop !== null && drag !== undefined && drag !== null) { //console.log(this); +if (drop.length === 3 && drag.length === 3) { //console.log(this); +xhr.open('GET', 'move/' + drag + '/' + drop , true); +//xhr.send(drag + ',' + drop); +xhr.send(null); +xhr.onload = function () { +if (xhr.status === 200) { +responseObject = JSON.parse(xhr.responseText); +if (responseObject.w.status.length === 1 || responseObject.w.status[1] !== 0) { +I(drag).setAttribute('src', 'i/' + responseObject.w.src[0] + '.png'); +I(drop).setAttribute('src', 'i/' + responseObject.w.src[1] + '.png'); +I(drag).id = responseObject.w.src[0]; +I(drop).id = responseObject.w.src[1]; +// TODO: Display status and/or sleep. +I(responseObject.b.src[1]).setAttribute('src', 'i/' + responseObject.b.src[0] + '.png'); +I(responseObject.b.dst[responseObject.b.dst.length-1]).setAttribute('src', 'i/' + responseObject.b.src[1] + '.png'); +I(responseObject.b.src[1]).id = responseObject.b.src[0]; +I(responseObject.b.dst[responseObject.b.dst.length-1]).id = responseObject.b.src[1]; +} +} +}; +} +//drag = null; +}} + +//for (b=0; C('coord').length > b; b++) {C('coord')[b].onmousemove = function () { +//if (drag !== null && drag !== undefined) {console.log(this.x + '.' + this.y)} +//if (drag !== null && drag !== undefined) {I(this.id).style.position = 'absolute'; I(this.id).style.left = this.x + 'px'; I(this.id).style.up = this.y + 'px'} +//}} + diff --git a/chess_gui/public/js/head.js b/chess_gui/public/js/head.js new file mode 100644 index 0000000..aa42426 --- /dev/null +++ b/chess_gui/public/js/head.js @@ -0,0 +1,6 @@ +function I(a) { + return document.getElementById(a); +} +function C(a) { + return document.getElementsByClassName(a); +} diff --git a/chess_gui/public/js/jquery.js b/chess_gui/public/js/jquery.js new file mode 100644 index 0000000..b061403 --- /dev/null +++ b/chess_gui/public/js/jquery.js @@ -0,0 +1,2 @@ +/*! jQuery v3.5.1 | (c) JS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.5.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,j=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function qe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function Le(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Oe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):("number"==typeof f.top&&(f.top+="px"),"number"==typeof f.left&&(f.left+="px"),c.css(f))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=$e(y.pixelPosition,function(e,t){if(t)return t=Be(e,n),Me.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0 1; +use_ok 'chess_gui'; diff --git a/chess_gui/t/002_index_route.t b/chess_gui/t/002_index_route.t new file mode 100644 index 0000000..c7bcb29 --- /dev/null +++ b/chess_gui/t/002_index_route.t @@ -0,0 +1,16 @@ +use strict; +use warnings; + +use chess_gui; +use Test::More tests => 2; +use Plack::Test; +use HTTP::Request::Common; +use Ref::Util qw; + +my $app = chess_gui->to_app; +ok( is_coderef($app), 'Got app' ); + +my $test = Plack::Test->create($app); +my $res = $test->request( GET '/' ); + +ok( $res->is_success, '[GET /] successful' ); diff --git a/chess_gui/views/index.tt b/chess_gui/views/index.tt new file mode 100644 index 0000000..2ffb115 --- /dev/null +++ b/chess_gui/views/index.tt @@ -0,0 +1,55 @@ + + + + + + + + + +Game of chess + + +
+

Title

+

Description

+
+
+
    1. A
    2. B
    3. C
    4. D
    5. E
    6. F
    7. G
    8. H
    [% FOREACH row IN board %]
    1. [% FOREACH item IN row %]
    2. [% END %]
  1. [% END %] + +

    + +

    + +
+
+ + + diff --git a/chess_gui/views/layouts/main.tt b/chess_gui/views/layouts/main.tt new file mode 100644 index 0000000..0f3de6f --- /dev/null +++ b/chess_gui/views/layouts/main.tt @@ -0,0 +1,23 @@ + + + + + + <% title %> + + + + + + + + +<% content %> + + +