Implementation of Lucifers Pastime
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

508 lines
8.9KB

  1. #!/usr/bin/perl
  2. use warnings;
  3. use strict;
  4. use utf8;
  5. my $XBOX_CHR = chr(0x2573);
  6. my $SHADE_CHR = chr(0x2591);
  7. my $ALT_US = chr(0x2017);
  8. my $ALT_PIPE = chr(0x2016);
  9. my $PAD_AXIS = " ";
  10. my $PAD_EVEN = " ";
  11. my $PAD_ODD = " ";
  12. my $HEX_1 = '-/--\-';
  13. my $HEX_2 = '| __ |';
  14. my $HEX_3 = '| |';
  15. my $HEX_S_1 = '-/--\-';
  16. my $HEX_S_2 = sprintf("|%s==%s|", $SHADE_CHR, $SHADE_CHR);
  17. my $HEX_S_3 = sprintf("|%s%s%s%s|", $SHADE_CHR, $SHADE_CHR, $SHADE_CHR, $SHADE_CHR);
  18. # my $HEX_S_1 = '-/--\-';
  19. # my $HEX_S_2 = '|'.$SHADE_CHR.'__'.$SHADE_CHR.'|';
  20. # my $HEX_S_3 = '|'.$SHADE_CHR.$SHADE_CHR.$SHADE_CHR.$SHADE_CHR.'|';
  21. my $HL_1 = "|_____";
  22. my $HL_2 = $ALT_PIPE.$ALT_US.$ALT_US.$ALT_US.$ALT_US.$ALT_US;
  23. my $SUB_CHR = "_";
  24. my $ALT_SUB_CHR = "=";
  25. my $BLANK_CELL_CHR = $ALT_US;
  26. my $PREF_1 = substr($HEX_1, -2, 2);
  27. my $PREF_2 = ' ';
  28. my $PREF_3 = ' ';
  29. my $TRAIL_1 = substr($HEX_1, 0, 1);
  30. my $TRAIL_2 = substr($HEX_1, -1, 1);
  31. my $TRAIL_3 = substr($HEX_1, 0, 2);
  32. # Pieces
  33. my $MG_A = "A"; # Apprentice
  34. my $MG_I = "I"; # Iron Maiden
  35. my $MG_N = "N"; # Nekomata
  36. my $MG_IT = "It"; # Ittan-Momen
  37. my $MG_H = "H"; # Harpy
  38. my $MG_S = "S"; # Slime
  39. my $MG_RC = "Rc"; # Redcap
  40. my $MG_RO = "Hs"; # Red Oni
  41. my $MG_HS = "Ro"; # Holstaur
  42. my $MG_B = "B"; # Blue Oni
  43. my $MG_P = "P"; # Preistess
  44. my $MG_IM = "Im"; # Imp
  45. my $MG_F = "F"; # False Angel
  46. my $MG_QS = "Qs"; # Queen slime
  47. my $MG_AU = "Au"; # Automaton
  48. my $MG_SY = "Sy"; # Sylph
  49. my $MG_Q = "Q"; # Queen
  50. # Players
  51. my $P1 = "P1";
  52. my $P2 = "P2";
  53. my $DIV = ":";
  54. my %AXIS = (
  55. "A" => 1,
  56. "B" => 2,
  57. "C" => 3,
  58. "D" => 4,
  59. "E" => 5,
  60. "F" => 6,
  61. "G" => 7,
  62. "H" => 8,
  63. "I" => 9,
  64. "J" => 10,
  65. "K" => 11
  66. );
  67. my %AXIS_RV = map {
  68. $AXIS{$_} => $_
  69. } keys(%AXIS);
  70. #
  71. # /--\ +1
  72. # | __ |
  73. # | |+1
  74. # \--/
  75. # -1 -1
  76. #
  77. # ODD
  78. # UP: 0, +1
  79. # DOWN: -1, -1
  80. # EVEN
  81. # UP: +1, +1
  82. # DOWN: +0, -1
  83. # [Row move, Diag move]
  84. my %MOVE = (
  85. $MG_A => [
  86. [-1, 1], [ 0, 1]
  87. ],
  88. $MG_Q => [
  89. [ 0, 1], [ 1, 0], [-1, 0], [ 0,-1],
  90. ],
  91. $MG_I => [
  92. [0,0]
  93. ],
  94. $MG_IT => [
  95. [ 0,-1], [ 1,-1]
  96. ],
  97. $MG_N => [
  98. [-1, 2],
  99. [ 1,-2]
  100. ],
  101. $MG_H => [
  102. [-3, 2], [-1,-2], [ 1, 2], [ 3,-2]
  103. ],
  104. $MG_RC => [
  105. [-1, 0], [-2, 0], [ 0, 1], [ 0, 2]
  106. ],
  107. $MG_S => [
  108. [-1, 1], [-2, 2], [ 0, 1], [ 0, 2],
  109. [ 0,-1], [ 0,-2], [ 1,-1], [ 2,-2],
  110. ],
  111. $MG_HS => [
  112. [-3, 1], [-2,-1], [ 2, 1], [ 3,-1]
  113. ],
  114. $MG_RO => [
  115. [-1, 1], [ 0, 1], [ 1, 1], [ 1,-2]
  116. ],
  117. $MG_B => [
  118. [-1, 1], [ 0, 1], [ 0,-2], [ 1,-2]
  119. ],
  120. $MG_P => [
  121. [-4, 2], [-2, 1], [-2,-2], [-1,-1],
  122. [ 1, 1], [ 2,-1], [ 2, 2], [ 4,-2]
  123. ],
  124. $MG_IM => [
  125. [-2, 1], [-1,-1], [-1, 2], [ 1, 1],
  126. [ 1,-1], [ 1,-2], [ 2,-1]
  127. ],
  128. $MG_F => [
  129. [-1, 0], [-1, 1], [ 0, 1], [ 0,-1],
  130. [ 1, 0], [ 1,-1]
  131. ],
  132. $MG_QS => [
  133. [-3, 3], [-2, 2], [-2, 0], [-1, 0],
  134. [-1, 1], [ 0, 1], [ 0, 2], [ 0, 3],
  135. [ 0,-1], [ 0,-2], [ 0,-3], [ 1, 0],
  136. [ 1,-1], [ 2, 0], [ 2,-2], [ 3,-3],
  137. ],
  138. $MG_AU => [
  139. [-1, 0], [-1, 1], [ 0, 1], [ 0,-1],
  140. [ 1, 0], [ 1,-1]
  141. ],
  142. $MG_SY => [
  143. [-4, 4], [-3, 3], [-3, 2], [-1,-2],
  144. [ 0,-2], [ 0,-3], [ 0, 3], [ 0, 4],
  145. [ 1, 2], [ 3,-2], [ 3,-3], [ 4,-4]
  146. ]
  147. );
  148. # Special cells
  149. my $EMPTY_CELL = "_";
  150. # Shade enum
  151. my $SHADED_ENUM = 1;
  152. my $EMPTY_ENUM = 0;
  153. my %SHADE = (
  154. $SHADED_ENUM => [$HEX_S_1, $HEX_S_2, $HEX_S_3],
  155. $EMPTY_ENUM => [$HEX_1, $HEX_2, $HEX_3]
  156. );
  157. my @sc0 = ();
  158. my %board;
  159. # Display pieces
  160. #==================================================
  161. # I hate this function
  162. sub f_1($$$){
  163. my $p = shift;
  164. my $c0 = shift;
  165. my $hex = shift;
  166. my $s0;
  167. $p =~ s/($P1|$P2)$DIV//;
  168. $p =~ s/$EMPTY_CELL//;
  169. $p .= "__" if length($p) < 1;
  170. $p .= "_" if length($p) < 2;
  171. $s0 = $hex;
  172. $s0 =~ s/$SUB_CHR{1,2}/$p/;
  173. if ($p eq "__"){
  174. $s0 =~ s/$ALT_SUB_CHR{1,2}/$SHADE_CHR$SHADE_CHR/;
  175. }else{
  176. $p =~ s/_/$SHADE_CHR/;
  177. $s0 =~ s/$ALT_SUB_CHR{1,2}/$p/;
  178. }
  179. if($c0 % 2 == 0){
  180. $s0 =~ s/$SUB_CHR/$BLANK_CELL_CHR/g;
  181. }
  182. return $s0;
  183. }
  184. # Display shade
  185. #==================================================
  186. sub shade_cell($){
  187. my $not = shift;
  188. push(@sc0, $not) unless shade_t($not);
  189. }
  190. sub shade_t($){
  191. my $not = shift;
  192. return $SHADED_ENUM if grep /^$not$/, @sc0;
  193. return $EMPTY_ENUM;
  194. }
  195. sub get_shade_chr($){
  196. my $en = shift;
  197. return $SHADE{$en};
  198. }
  199. sub shade_lookup($$){
  200. my ($r0, $c0) = (shift, shift);
  201. my $not;
  202. $not = cell_index_rev($c0, $r0);
  203. return get_shade_chr(shade_t($not));
  204. }
  205. # Display lines
  206. #==================================================
  207. sub disp_1($$){
  208. my ($r0, $c0) = (shift, shift);
  209. my $hex;
  210. $hex = shade_lookup($r0, $c0)->[0];
  211. return $hex;
  212. # return $HEX_1;
  213. }
  214. sub disp_2($$){
  215. my ($r0, $c0) = (shift, shift);
  216. my $p;
  217. my $not;
  218. my $hex;
  219. $hex = shade_lookup($r0, $c0)->[1];
  220. $not = cell_index_rev($c0, $r0);
  221. $p = $board{$not};
  222. return f_1($p, $c0, $hex);
  223. # my ($r0, $c0) = (shift, shift);
  224. # return $HEX_2;
  225. }
  226. sub disp_3($$){
  227. my ($r0, $c0) = (shift, shift);
  228. my $hex;
  229. $hex = shade_lookup($r0, $c0)->[2];
  230. return $hex;
  231. }
  232. sub disp_y_axis($$$$){
  233. my ($s0, $s1, $s2, $r0) = @_;
  234. my $n0;
  235. $n0 = length($r0);
  236. $s0 = $r0 % 2 == 1 ? $PAD_ODD : $PAD_EVEN.$PREF_1;
  237. $s1 = $r0 % 2 == 1 ? $PAD_ODD : $PAD_EVEN.$PREF_2;
  238. $s1 =~ s/^ {$n0}/$r0/;
  239. $s2 = $r0 % 2 == 1 ? $PAD_ODD : $PAD_EVEN.$PREF_3;
  240. return ($s0, $s1, $s2);
  241. }
  242. # Display cell
  243. #==================================================
  244. sub add_cell($$$$$){
  245. my ($s0, $s1, $s2, $r0, $c0) = @_;
  246. $s0 .= disp_1($r0, $c0);
  247. $s1 .= disp_2($r0, $c0);
  248. $s2 .= disp_3($r0, $c0);
  249. # if($c0 % 2 == 0){
  250. # $s0 =~ s/ /$SHADE_CHR/g;
  251. # $s1 =~ s/ /$SHADE_CHR/g;
  252. # $s2 =~ s/ /$SHADE_CHR/g;
  253. # }
  254. return ($s0, $s1, $s2);
  255. }
  256. sub disp_0($){
  257. my $r0;
  258. my ($s0, $s1, $s2);
  259. $r0 = shift;
  260. # Append the y axis
  261. ($s0, $s1, $s2) = disp_y_axis($s0, $s1, $s2, $r0);
  262. # Iterate through the cells
  263. for my $i (1..11){
  264. ($s0, $s1, $s2) = add_cell($s0, $s1, $s2, $r0, $i);
  265. }
  266. return $s0."\n".$s1."\n".$s2."\n";
  267. }
  268. # Display row
  269. #==================================================
  270. sub disp_row($){
  271. my $row;
  272. my $r0;
  273. $r0 = shift;
  274. $row = disp_0($r0);
  275. # Handle trailing characters
  276. if($r0 % 2 == 1){
  277. # Trim the start of the first line
  278. $row =~ s/$TRAIL_1/ /;
  279. # Trim the end of the first line
  280. $row =~ s/\n/$TRAIL_3\n/
  281. }else{
  282. # Trim the end of the last line
  283. $row =~ s/$TRAIL_2\n/ \n/m;
  284. }
  285. return $row;
  286. }
  287. sub disp_trailing_row(){
  288. my $s0;
  289. my $s1;
  290. $s0 = $PAD_EVEN.$PREF_1;
  291. # Clear some chars from
  292. # our hex patterns
  293. $s1 = $HEX_1;
  294. substr($s1, 2,2) = " ";
  295. # Append hex pattern to
  296. # trailing row
  297. for my $i (1..11){
  298. $s0 .= $s1;
  299. }
  300. # Clear one last pair of
  301. # chrs
  302. substr($s0, -2,2) = " ";
  303. $s0 .= "\n";
  304. return $s0;
  305. }
  306. sub disp_x_axis(){
  307. my $s0;
  308. $s0 = $PAD_AXIS;
  309. $s0 .= join(
  310. $PAD_AXIS, map{
  311. $AXIS_RV{$_}
  312. }(1..11));
  313. $s0 .= "\n";
  314. $s0 .= $PAD_AXIS;
  315. $s0 .= join(
  316. "", map{
  317. $_ % 2 == 1 ? $HL_1 : $HL_2
  318. }(1..11));
  319. $s0 .= "\n";
  320. return $s0
  321. }
  322. # Display board
  323. #==================================================
  324. sub disp_board(){
  325. my $b;
  326. for my $i (map {11-$_+1} (1..11)) {
  327. $b .= disp_row($i);
  328. }
  329. $b .= disp_trailing_row();
  330. $b .= disp_x_axis();
  331. $b =~ s/$TRAIL_1$TRAIL_3\n/\n/m;
  332. for my $i (1..11-1){
  333. substr($b, 2+6*$i, 2) = " ";
  334. }
  335. printf("%s", $b);
  336. }
  337. sub cell_index_rev($$){
  338. return $AXIS_RV{$_[0]}.$_[1];
  339. }
  340. sub cell_index($){
  341. my ($chr1, $chr2) = (split(//, $_[0]));
  342. return ($AXIS{$chr1}, $chr2);
  343. }
  344. sub apply_shift($$){
  345. my ($not, $my_shift) = (shift, shift);
  346. my $r0;
  347. my $c0;
  348. ($r0, $c0) = cell_index($not);
  349. $r0 += $my_shift->[0];
  350. $c0 += $my_shift->[1];
  351. die "cell index [$r0, $c0]: out of bound exception" if $r0 > 11 or $c0 > 11 or $r0 < 1 or $c0 < 1;
  352. return cell_index_rev($r0, $c0);
  353. }
  354. sub calc_move($$){
  355. my ($not, $mov) = (shift, shift);
  356. my $r0;
  357. my $c0;
  358. my $x_shift;
  359. my $y_shift;
  360. my $n0;
  361. my $ni;
  362. ($c0, $r0) = cell_index($not);
  363. # get y_shift
  364. $y_shift = $mov->[1];
  365. # get x_shift
  366. $x_shift = $mov->[0];
  367. # make x_shift adjustment
  368. $ni = $y_shift != 0 ? ($y_shift / ($y_shift * -1)) : -1;
  369. $ni *= -1;
  370. $n0 = ($r0 + 1) % 2;
  371. $x_shift += int(($y_shift + ($n0 * $ni)) / 2);
  372. return apply_shift($not, [$x_shift, $y_shift]);
  373. }
  374. # Main starts here!
  375. binmode(STDOUT, ":utf8");
  376. # Creates a hash of the the form
  377. # $board{cell_notation} = piece_enum
  378. %board = map {
  379. $_ => $EMPTY_CELL
  380. } map {
  381. my $l0;
  382. $l0 = $_;
  383. (map {$l0.$_} ("1".."11"))
  384. } map {
  385. $AXIS_RV{$_}
  386. }(1...11);
  387. my $m1 = "E6";
  388. my $c1 = $MG_A;
  389. $board{$m1} = $P1.$DIV.$c1;
  390. # for my $mv (@{$MOVE{$c1}}){
  391. # printf("%s\n", calc_move($m1, $mv));
  392. # }
  393. disp_board();