Implementation of Lucifers Pastime
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

824 line
20KB

  1. #!/usr/bin/perl
  2. use warnings;
  3. use strict;
  4. use utf8;
  5. my $ARRAY = "ARRAY";
  6. my $HAND_SIZE = 5;
  7. my $X_BOX_CHR = chr(0x2573);
  8. my $GRAY_BOX_CHR = chr(0x2591);
  9. my $ALT_US = chr(0x2017);
  10. my $ALT_PIPE = chr(0x2016);
  11. my $SHADE_1_CHR = $GRAY_BOX_CHR;
  12. my $SHADE_2_CHR = $X_BOX_CHR;
  13. my $PAD_AXIS = " ";
  14. my $PAD_EVEN = " ";
  15. my $PAD_ODD = " ";
  16. my $HEX_1 = '-/--\-';
  17. my $HEX_2 = '| __ |';
  18. my $HEX_3 = '| |';
  19. my $HEX_S1_1 = '-/--\-';
  20. my $HEX_S1_2 = sprintf("|%s%s%s%s|", $SHADE_1_CHR, $SHADE_1_CHR, $SHADE_1_CHR, $SHADE_1_CHR);
  21. my $HEX_S1_3 = sprintf("|%s%s%s%s|", $SHADE_1_CHR, $SHADE_1_CHR, $SHADE_1_CHR, $SHADE_1_CHR);
  22. my $HEX_S2_1 = '-/--\-';
  23. my $HEX_S2_2 = sprintf("|%s%s%s%s|", $SHADE_2_CHR, $SHADE_2_CHR, $SHADE_2_CHR, $SHADE_2_CHR);
  24. my $HEX_S2_3 = sprintf("|%s%s%s%s|", $SHADE_2_CHR, $SHADE_2_CHR, $SHADE_2_CHR, $SHADE_2_CHR);
  25. my $HEX_S3_1 = '-/--\-';
  26. my $HEX_S3_2 = sprintf("|%s%s%s%s|", $SHADE_2_CHR, $SHADE_2_CHR, $SHADE_1_CHR, $SHADE_1_CHR);
  27. my $HEX_S3_3 = sprintf("|%s%s%s%s|", $SHADE_2_CHR, $SHADE_2_CHR, $SHADE_1_CHR, $SHADE_1_CHR);
  28. my $HL_1 = "|____ ";
  29. my $HL_2 = $ALT_PIPE.$ALT_US.$ALT_US.$ALT_US.$ALT_US." ";
  30. my $SUB_CHR = "_";
  31. my $BLANK_CELL_CHR = $ALT_US;
  32. my $PREF_1 = substr($HEX_1, -2, 2);
  33. my $PREF_2 = ' ';
  34. my $PREF_3 = ' ';
  35. my $TRAIL_1 = substr($HEX_1, 0, 1);
  36. my $TRAIL_2 = substr($HEX_1, -1, 1);
  37. my $TRAIL_3 = substr($HEX_1, 0, 2);
  38. # Pieces
  39. my $MG_A = "A"; # Apprentice
  40. my $MG_I = "I"; # Iron Maiden
  41. my $MG_N = "N"; # Nekomata
  42. my $MG_IT = "It"; # Ittan-Momen
  43. my $MG_H = "H"; # Harpy
  44. my $MG_S = "S"; # Slime
  45. my $MG_RC = "Rc"; # Redcap
  46. my $MG_HS = "Hs"; # Holstaur
  47. my $MG_RO = "Ro"; # Red Oni
  48. my $MG_B = "B"; # Blue Oni
  49. my $MG_P = "P"; # Preistess
  50. my $MG_IM = "Im"; # Imp
  51. my $MG_F = "F"; # False Angel
  52. my $MG_QS = "Qs"; # Queen slime
  53. my $MG_AU = "Au"; # Automaton
  54. my $MG_SY = "Sy"; # Sylph
  55. my $MG_Q = "Q"; # Queen
  56. my @MG_PI = (
  57. $MG_A, $MG_I, $MG_N, $MG_IT, $MG_H, $MG_S,
  58. $MG_RC, $MG_HS, $MG_RO, $MG_B, $MG_P, $MG_IM,
  59. $MG_F, $MG_QS, $MG_AU, $MG_SY, $MG_Q
  60. );
  61. # Players
  62. my $P1 = "P1";
  63. my $P2 = "P2";
  64. my $DIV = ":";
  65. my %AXIS = (
  66. "A" => 1,
  67. "B" => 2,
  68. "C" => 3,
  69. "D" => 4,
  70. "E" => 5,
  71. "F" => 6,
  72. "G" => 7,
  73. "H" => 8,
  74. "I" => 9,
  75. "J" => 10,
  76. "K" => 11
  77. );
  78. my %AXIS_RV = map {
  79. $AXIS{$_} => $_
  80. } keys(%AXIS);
  81. package MoveStruct;
  82. use warnings;
  83. use strict;
  84. sub new {
  85. my $class = shift;
  86. my $self = { @_ };
  87. die "invalid MoveStruct {\"mov\"}" unless $self->{"mov"};
  88. die "invalid MoveStruct ->{\"type\"}" unless $self->{"type"};
  89. die "invalid MoveStruct type" unless ref($self->{"mov"}) eq $ARRAY;
  90. return bless $self, $class;
  91. }
  92. package LPST;
  93. #
  94. # /--\ +1
  95. # | __ |
  96. # | |+1
  97. # \--/
  98. # -1 -1
  99. #
  100. # ODD
  101. # UP: 0, +1
  102. # DOWN: -1, -1
  103. # EVEN
  104. # UP: +1, +1
  105. # DOWN: +0, -1
  106. # [Row move, Diag move]
  107. # Special cells
  108. my $EMPTY_CELL = "_";
  109. # Shade enum
  110. my $SHADE_3_ENUM = 0b011;
  111. my $SHADE_2_ENUM = 0b010;
  112. my $SHADE_1_ENUM = 0b001;
  113. my $EMPTY_ENUM = 0;
  114. my %SHADE = (
  115. $SHADE_1_ENUM => [$HEX_S1_1, $HEX_S1_2, $HEX_S1_3],
  116. $SHADE_2_ENUM => [$HEX_S2_1, $HEX_S2_2, $HEX_S2_3],
  117. $SHADE_3_ENUM => [$HEX_S3_1, $HEX_S3_2, $HEX_S3_3],
  118. $EMPTY_ENUM => [$HEX_1, $HEX_2, $HEX_3]
  119. );
  120. my $MOVE_ENUM = $SHADE_1_ENUM;
  121. my $BLOCK_ENUM = $SHADE_2_ENUM;
  122. my $MOVBLOCK_ENUM = $SHADE_3_ENUM;
  123. my $ERR_C_1 = -1;
  124. my %MOVE = (
  125. $MG_A => [
  126. MoveStruct->new("mov" => [-1, 1], "type" => $MOVBLOCK_ENUM),
  127. MoveStruct->new("mov" => [ 0, 1], "type" => $MOVBLOCK_ENUM)
  128. ],
  129. $MG_Q => [
  130. MoveStruct->new("mov" => [ 0, 1], "type" => $MOVE_ENUM),
  131. MoveStruct->new("mov" => [ 1, 0], "type" => $MOVE_ENUM),
  132. MoveStruct->new("mov" => [-1, 0], "type" => $MOVE_ENUM),
  133. MoveStruct->new("mov" => [ 0,-1], "type" => $MOVE_ENUM)
  134. ],
  135. $MG_I => [
  136. MoveStruct->new("mov" => [-1, 0], "type" => $BLOCK_ENUM),
  137. MoveStruct->new("mov" => [-1, 1], "type" => $BLOCK_ENUM),
  138. MoveStruct->new("mov" => [ 0, 1], "type" => $BLOCK_ENUM),
  139. MoveStruct->new("mov" => [ 0,-1], "type" => $BLOCK_ENUM),
  140. MoveStruct->new("mov" => [ 1, 0], "type" => $BLOCK_ENUM),
  141. MoveStruct->new("mov" => [ 1,-1], "type" => $BLOCK_ENUM)
  142. ],
  143. $MG_IT => [
  144. MoveStruct->new("mov" => [ 0,-1], "type" => $MOVE_ENUM),
  145. MoveStruct->new("mov" => [ 1,-1], "type" => $MOVE_ENUM),
  146. MoveStruct->new("mov" => [-1, 1], "type" => $BLOCK_ENUM),
  147. MoveStruct->new("mov" => [ 0, 1], "type" => $BLOCK_ENUM)
  148. ],
  149. $MG_N => [
  150. MoveStruct->new("mov" => [-1, 2], "type" => $MOVE_ENUM),
  151. MoveStruct->new("mov" => [ 1,-2], "type" => $MOVE_ENUM),
  152. MoveStruct->new("mov" => [-1, 1], "type" => $BLOCK_ENUM),
  153. MoveStruct->new("mov" => [ 0, 1], "type" => $BLOCK_ENUM)
  154. ],
  155. $MG_H => [
  156. MoveStruct->new("mov" => [-3, 2], "type" => $MOVE_ENUM),
  157. MoveStruct->new("mov" => [-1,-2], "type" => $MOVE_ENUM),
  158. MoveStruct->new("mov" => [ 1, 2], "type" => $MOVE_ENUM),
  159. MoveStruct->new("mov" => [ 3,-2], "type" => $MOVE_ENUM),
  160. MoveStruct->new("mov" => [ 0,-1], "type" => $BLOCK_ENUM),
  161. MoveStruct->new("mov" => [ 1,-1], "type" => $BLOCK_ENUM),
  162. MoveStruct->new("mov" => [-1, 1], "type" => $BLOCK_ENUM),
  163. MoveStruct->new("mov" => [ 0, 1], "type" => $BLOCK_ENUM)
  164. ],
  165. $MG_RC => [
  166. MoveStruct->new("mov" => [-1, 0], "type" => $MOVE_ENUM),
  167. MoveStruct->new("mov" => [-2, 0], "type" => $MOVE_ENUM),
  168. MoveStruct->new("mov" => [ 1, 0], "type" => $MOVE_ENUM),
  169. MoveStruct->new("mov" => [ 2, 0], "type" => $MOVE_ENUM),
  170. MoveStruct->new("mov" => [ 0,-1], "type" => $BLOCK_ENUM),
  171. MoveStruct->new("mov" => [ 1,-1], "type" => $BLOCK_ENUM),
  172. MoveStruct->new("mov" => [-1, 1], "type" => $BLOCK_ENUM),
  173. MoveStruct->new("mov" => [ 0, 1], "type" => $BLOCK_ENUM)
  174. ],
  175. $MG_S => [
  176. MoveStruct->new("mov" => [-1, 1], "type" => $MOVE_ENUM),
  177. MoveStruct->new("mov" => [-2, 2], "type" => $MOVE_ENUM),
  178. MoveStruct->new("mov" => [ 0, 1], "type" => $MOVE_ENUM),
  179. MoveStruct->new("mov" => [ 0, 2], "type" => $MOVE_ENUM),
  180. MoveStruct->new("mov" => [ 0,-1], "type" => $MOVE_ENUM),
  181. MoveStruct->new("mov" => [ 0,-2], "type" => $MOVE_ENUM),
  182. MoveStruct->new("mov" => [ 1,-1], "type" => $MOVE_ENUM),
  183. MoveStruct->new("mov" => [ 2,-2], "type" => $MOVE_ENUM),
  184. ],
  185. $MG_HS => [
  186. MoveStruct->new("mov" => [-3, 1], "type" => $MOVE_ENUM),
  187. MoveStruct->new("mov" => [-2,-1], "type" => $MOVE_ENUM),
  188. MoveStruct->new("mov" => [ 2, 1], "type" => $MOVE_ENUM),
  189. MoveStruct->new("mov" => [ 3,-1], "type" => $MOVE_ENUM),
  190. MoveStruct->new("mov" => [-2, 1], "type" => $BLOCK_ENUM),
  191. MoveStruct->new("mov" => [ 1, 1], "type" => $BLOCK_ENUM),
  192. MoveStruct->new("mov" => [-1, 1], "type" => $BLOCK_ENUM),
  193. MoveStruct->new("mov" => [ 0, 1], "type" => $BLOCK_ENUM)
  194. ],
  195. $MG_RO => [
  196. MoveStruct->new("mov" => [-1, 1], "type" => $MOVE_ENUM),
  197. MoveStruct->new("mov" => [ 0, 1], "type" => $MOVE_ENUM),
  198. MoveStruct->new("mov" => [ 1, 1], "type" => $MOVE_ENUM),
  199. MoveStruct->new("mov" => [ 1,-2], "type" => $MOVE_ENUM),
  200. MoveStruct->new("mov" => [-1, 0], "type" => $BLOCK_ENUM),
  201. MoveStruct->new("mov" => [ 1, 0], "type" => $BLOCK_ENUM)
  202. ],
  203. $MG_B => [
  204. MoveStruct->new("mov" => [-1, 1], "type" => $MOVE_ENUM),
  205. MoveStruct->new("mov" => [ 0, 1], "type" => $MOVE_ENUM),
  206. MoveStruct->new("mov" => [ 0,-2], "type" => $MOVE_ENUM),
  207. MoveStruct->new("mov" => [ 2,-2], "type" => $MOVE_ENUM),
  208. MoveStruct->new("mov" => [ 0,-1], "type" => $BLOCK_ENUM),
  209. MoveStruct->new("mov" => [ 1,-1], "type" => $BLOCK_ENUM)
  210. ],
  211. $MG_P => [
  212. MoveStruct->new("mov" => [-4, 2], "type" => $MOVE_ENUM),
  213. MoveStruct->new("mov" => [-2, 1], "type" => $MOVBLOCK_ENUM),
  214. MoveStruct->new("mov" => [-2,-2], "type" => $MOVE_ENUM),
  215. MoveStruct->new("mov" => [-1,-1], "type" => $MOVBLOCK_ENUM),
  216. MoveStruct->new("mov" => [ 1, 1], "type" => $MOVBLOCK_ENUM),
  217. MoveStruct->new("mov" => [ 2,-1], "type" => $MOVBLOCK_ENUM),
  218. MoveStruct->new("mov" => [ 2, 2], "type" => $MOVE_ENUM),
  219. MoveStruct->new("mov" => [ 4,-2], "type" => $MOVE_ENUM)
  220. ],
  221. $MG_IM => [
  222. MoveStruct->new("mov" => [-2, 1], "type" => $MOVBLOCK_ENUM),
  223. MoveStruct->new("mov" => [-1,-1], "type" => $MOVBLOCK_ENUM),
  224. MoveStruct->new("mov" => [-1, 2], "type" => $MOVBLOCK_ENUM),
  225. MoveStruct->new("mov" => [ 1, 1], "type" => $MOVBLOCK_ENUM),
  226. MoveStruct->new("mov" => [ 1,-1], "type" => $MOVE_ENUM),
  227. MoveStruct->new("mov" => [ 1,-2], "type" => $BLOCK_ENUM),
  228. MoveStruct->new("mov" => [ 2,-1], "type" => $MOVBLOCK_ENUM)
  229. ],
  230. $MG_F => [
  231. MoveStruct->new("mov" => [-1, 0], "type" => $MOVE_ENUM),
  232. MoveStruct->new("mov" => [-1, 1], "type" => $MOVE_ENUM),
  233. MoveStruct->new("mov" => [ 0, 1], "type" => $MOVE_ENUM),
  234. MoveStruct->new("mov" => [ 0,-1], "type" => $MOVE_ENUM),
  235. MoveStruct->new("mov" => [ 1, 0], "type" => $MOVE_ENUM),
  236. MoveStruct->new("mov" => [ 1,-1], "type" => $MOVE_ENUM),
  237. MoveStruct->new("mov" => [ 0, 2], "type" => $BLOCK_ENUM),
  238. MoveStruct->new("mov" => [ 0,-2], "type" => $BLOCK_ENUM),
  239. MoveStruct->new("mov" => [ 1, 1], "type" => $BLOCK_ENUM),
  240. MoveStruct->new("mov" => [ 1,-2], "type" => $BLOCK_ENUM),
  241. MoveStruct->new("mov" => [ 2, 0], "type" => $BLOCK_ENUM),
  242. MoveStruct->new("mov" => [ 2,-1], "type" => $BLOCK_ENUM),
  243. MoveStruct->new("mov" => [ 2,-2], "type" => $BLOCK_ENUM),
  244. MoveStruct->new("mov" => [-1, 2], "type" => $BLOCK_ENUM),
  245. MoveStruct->new("mov" => [-1,-1], "type" => $BLOCK_ENUM),
  246. MoveStruct->new("mov" => [-2, 0], "type" => $BLOCK_ENUM),
  247. MoveStruct->new("mov" => [-2, 1], "type" => $BLOCK_ENUM),
  248. MoveStruct->new("mov" => [-2, 2], "type" => $BLOCK_ENUM)
  249. ],
  250. $MG_QS => [
  251. MoveStruct->new("mov" => [-3, 3], "type" => $MOVE_ENUM),
  252. MoveStruct->new("mov" => [-2, 2], "type" => $MOVE_ENUM),
  253. MoveStruct->new("mov" => [-2, 0], "type" => $MOVE_ENUM),
  254. MoveStruct->new("mov" => [-1, 0], "type" => $MOVE_ENUM),
  255. MoveStruct->new("mov" => [-1, 1], "type" => $MOVE_ENUM),
  256. MoveStruct->new("mov" => [ 0, 1], "type" => $MOVE_ENUM),
  257. MoveStruct->new("mov" => [ 0, 2], "type" => $MOVE_ENUM),
  258. MoveStruct->new("mov" => [ 0, 3], "type" => $MOVE_ENUM),
  259. MoveStruct->new("mov" => [ 0,-1], "type" => $MOVE_ENUM),
  260. MoveStruct->new("mov" => [ 0,-2], "type" => $MOVE_ENUM),
  261. MoveStruct->new("mov" => [ 0,-3], "type" => $MOVE_ENUM),
  262. MoveStruct->new("mov" => [ 1, 0], "type" => $MOVE_ENUM),
  263. MoveStruct->new("mov" => [ 1,-1], "type" => $MOVE_ENUM),
  264. MoveStruct->new("mov" => [ 2, 0], "type" => $MOVE_ENUM),
  265. MoveStruct->new("mov" => [ 2,-2], "type" => $MOVE_ENUM),
  266. MoveStruct->new("mov" => [ 3,-3], "type" => $MOVE_ENUM),
  267. MoveStruct->new("mov" => [ 3, 0], "type" => $MOVE_ENUM),
  268. MoveStruct->new("mov" => [-3, 0], "type" => $MOVE_ENUM)
  269. ],
  270. $MG_AU => [
  271. MoveStruct->new("mov" => [-1, 0], "type" => $MOVBLOCK_ENUM),
  272. MoveStruct->new("mov" => [-1, 1], "type" => $MOVBLOCK_ENUM),
  273. MoveStruct->new("mov" => [ 0, 1], "type" => $MOVBLOCK_ENUM),
  274. MoveStruct->new("mov" => [ 0,-1], "type" => $MOVBLOCK_ENUM),
  275. MoveStruct->new("mov" => [ 1, 0], "type" => $MOVBLOCK_ENUM),
  276. MoveStruct->new("mov" => [ 1,-1], "type" => $MOVBLOCK_ENUM),
  277. MoveStruct->new("mov" => [ 0, 2], "type" => $BLOCK_ENUM),
  278. MoveStruct->new("mov" => [ 0,-2], "type" => $BLOCK_ENUM),
  279. MoveStruct->new("mov" => [ 1, 1], "type" => $BLOCK_ENUM),
  280. MoveStruct->new("mov" => [ 1,-2], "type" => $BLOCK_ENUM),
  281. MoveStruct->new("mov" => [ 2,-1], "type" => $BLOCK_ENUM),
  282. MoveStruct->new("mov" => [ 2,-2], "type" => $BLOCK_ENUM),
  283. MoveStruct->new("mov" => [-1, 2], "type" => $BLOCK_ENUM),
  284. MoveStruct->new("mov" => [-1,-1], "type" => $BLOCK_ENUM),
  285. MoveStruct->new("mov" => [-2, 1], "type" => $BLOCK_ENUM),
  286. MoveStruct->new("mov" => [-2, 2], "type" => $BLOCK_ENUM)
  287. ],
  288. $MG_SY => [
  289. MoveStruct->new("mov" => [-4, 4], "type" => $MOVE_ENUM),
  290. MoveStruct->new("mov" => [-3, 3], "type" => $MOVE_ENUM),
  291. MoveStruct->new("mov" => [-3, 2], "type" => $MOVBLOCK_ENUM),
  292. MoveStruct->new("mov" => [-1,-2], "type" => $MOVBLOCK_ENUM),
  293. MoveStruct->new("mov" => [ 0,-4], "type" => $MOVE_ENUM),
  294. MoveStruct->new("mov" => [ 0,-3], "type" => $MOVE_ENUM),
  295. MoveStruct->new("mov" => [ 0, 3], "type" => $MOVE_ENUM),
  296. MoveStruct->new("mov" => [ 0, 4], "type" => $MOVE_ENUM),
  297. MoveStruct->new("mov" => [ 1, 2], "type" => $MOVBLOCK_ENUM),
  298. MoveStruct->new("mov" => [ 3,-2], "type" => $MOVBLOCK_ENUM),
  299. MoveStruct->new("mov" => [ 3,-3], "type" => $MOVE_ENUM),
  300. MoveStruct->new("mov" => [ 4,-4], "type" => $MOVE_ENUM),
  301. MoveStruct->new("mov" => [-1, 1], "type" => $BLOCK_ENUM),
  302. MoveStruct->new("mov" => [ 0, 1], "type" => $BLOCK_ENUM),
  303. MoveStruct->new("mov" => [ 0,-1], "type" => $BLOCK_ENUM),
  304. MoveStruct->new("mov" => [ 1,-1], "type" => $BLOCK_ENUM)
  305. ]
  306. );
  307. my %sc = ();
  308. my %board;
  309. # Display pieces
  310. #==================================================
  311. sub get_pi_str($){
  312. my $p = shift;
  313. $p =~ s/($P1|$P2)$DIV//;
  314. $p .= "_" if length($p) < 2;
  315. return $p;
  316. }
  317. sub sub_pi_str($$$){
  318. my ($p, $c0, $hex) = (shift, shift, shift);
  319. my $s0;
  320. $p = get_pi_str($p);
  321. $s0 = $hex;
  322. unless($p eq "__"){
  323. substr($s0, 2,2) = $p;
  324. }
  325. if($c0 % 2 == 0){
  326. $s0 =~ s/$SUB_CHR/$BLANK_CELL_CHR/g;
  327. }
  328. return $s0;
  329. }
  330. # Display shade
  331. #==================================================
  332. sub apply_shade($$){
  333. my $not = shift;
  334. my $en = shift;
  335. $sc{$not} = $en unless (grep /^$not$/, keys(%sc));
  336. }
  337. sub get_shade_en($){
  338. my $not = shift;
  339. return $sc{$not} if (grep /^$not$/, keys(%sc));
  340. return $EMPTY_ENUM;
  341. }
  342. sub get_shade_hex($){
  343. my $en = shift;
  344. return $SHADE{$en};
  345. }
  346. sub get_cell_shade($$){
  347. my ($r0, $c0) = (shift, shift);
  348. my $not;
  349. $not = cell_index_rev($c0, $r0);
  350. return get_shade_hex(get_shade_en($not));
  351. }
  352. # Display lines
  353. #==================================================
  354. sub disp_1($$){
  355. my ($r0, $c0) = (shift, shift);
  356. my $hex;
  357. $hex = get_cell_shade($r0, $c0)->[0];
  358. return $hex;
  359. }
  360. sub disp_2($$){
  361. my ($r0, $c0) = (shift, shift);
  362. my $p;
  363. my $not;
  364. my $hex;
  365. $hex = get_cell_shade($r0, $c0)->[1];
  366. $not = cell_index_rev($c0, $r0);
  367. $p = $board{$not};
  368. return sub_pi_str($p, $c0, $hex);
  369. }
  370. sub disp_3($$){
  371. my ($r0, $c0) = (shift, shift);
  372. my $hex;
  373. $hex = get_cell_shade($r0, $c0)->[2];
  374. return $hex;
  375. }
  376. sub disp_y_axis($$$$){
  377. my ($s0, $s1, $s2, $r0) = @_;
  378. my $n0;
  379. $n0 = length($r0);
  380. $s0 = $r0 % 2 == 1 ? $PAD_ODD : $PAD_EVEN.$PREF_1;
  381. $s1 = $r0 % 2 == 1 ? $PAD_ODD : $PAD_EVEN.$PREF_2;
  382. $s1 =~ s/^ {$n0}/$r0/;
  383. $s2 = $r0 % 2 == 1 ? $PAD_ODD : $PAD_EVEN.$PREF_3;
  384. return ($s0, $s1, $s2);
  385. }
  386. # Display cell
  387. #==================================================
  388. sub add_cell($$$$$){
  389. my ($s0, $s1, $s2, $r0, $c0) = @_;
  390. $s0 .= disp_1($r0, $c0);
  391. $s1 .= disp_2($r0, $c0);
  392. $s2 .= disp_3($r0, $c0);
  393. return ($s0, $s1, $s2);
  394. }
  395. sub disp_0($){
  396. my $r0;
  397. my ($s0, $s1, $s2);
  398. $r0 = shift;
  399. # Append the y axis
  400. ($s0, $s1, $s2) = disp_y_axis($s0, $s1, $s2, $r0);
  401. # Iterate through the cells
  402. for my $i (1..11){
  403. ($s0, $s1, $s2) = add_cell($s0, $s1, $s2, $r0, $i);
  404. }
  405. return $s0."\n".$s1."\n".$s2."\n";
  406. }
  407. # Display row
  408. #==================================================
  409. sub disp_row($){
  410. my $row;
  411. my $r0;
  412. $r0 = shift;
  413. $row = disp_0($r0);
  414. # Handle trailing characters
  415. if($r0 % 2 == 1){
  416. # Trim the start of the first line
  417. $row =~ s/$TRAIL_1/ /;
  418. # Trim the end of the first line
  419. $row =~ s/\n/$TRAIL_3\n/
  420. }else{
  421. # Trim the end of the last line
  422. $row =~ s/$TRAIL_2\n/ \n/m;
  423. }
  424. return $row;
  425. }
  426. sub disp_trailing_row(){
  427. my $s0;
  428. my $s1;
  429. $s0 = $PAD_EVEN.$PREF_1;
  430. # Clear some chars from
  431. # our hex patterns
  432. $s1 = $HEX_1;
  433. substr($s1, 2,2) = " ";
  434. # Append hex pattern to
  435. # trailing row
  436. for my $i (1..11){
  437. $s0 .= $s1;
  438. }
  439. # Clear one last pair of
  440. # chrs
  441. substr($s0, -2,2) = " ";
  442. $s0 .= "\n";
  443. return $s0;
  444. }
  445. sub disp_x_axis(){
  446. my $s0;
  447. $s0 = $PAD_AXIS;
  448. $s0 .= join(
  449. $PAD_AXIS, map{
  450. $AXIS_RV{$_}
  451. }(1..11));
  452. $s0 .= "\n";
  453. $s0 .= $PAD_AXIS;
  454. $s0 .= join(
  455. "", map{
  456. $_ % 2 == 1 ? $HL_1 : $HL_2
  457. }(1..11));
  458. $s0 .= "\n";
  459. return $s0
  460. }
  461. # Display board
  462. #==================================================
  463. sub disp_board(){
  464. my $b;
  465. for my $i (map {11-$_+1} (1..11)) {
  466. $b .= disp_row($i);
  467. }
  468. $b .= disp_trailing_row();
  469. $b .= disp_x_axis();
  470. $b =~ s/$TRAIL_1$TRAIL_3\n/\n/m;
  471. for my $i (1..11-1){
  472. substr($b, 2+6*$i, 2) = " ";
  473. }
  474. printf("%s", $b);
  475. }
  476. # Caclulate movement
  477. #==================================================
  478. sub pi_split($$){
  479. my ($not, $i0) = (shift, shift);
  480. return (split(/$DIV/, $board{$not}))[$i0];
  481. }
  482. sub cell_pi($){
  483. my $not = shift;
  484. return pi_split($not, 1);
  485. }
  486. sub cell_pl($){
  487. my $not = shift;
  488. return pi_split($not, 0);
  489. }
  490. sub cell_index_rev($$){
  491. return $AXIS_RV{$_[0]}.$_[1];
  492. }
  493. sub cell_index($){
  494. my $chr1 = substr($_[0], 0,1);
  495. my $chr2 = substr($_[0], 1,length($_[0])-1);
  496. return ($AXIS{$chr1}, $chr2);
  497. }
  498. sub apply_shift($$){
  499. my ($not, $my_shift) = (shift, shift);
  500. my $r0;
  501. my $c0;
  502. ($r0, $c0) = cell_index($not);
  503. $r0 += $my_shift->[0];
  504. $c0 += $my_shift->[1];
  505. return $ERR_C_1 if $r0 > 11 or $c0 > 11 or $r0 < 1 or $c0 < 1;
  506. return cell_index_rev($r0, $c0);
  507. }
  508. sub calc_new_cell($$){
  509. my ($not, $mov) = (shift, shift);
  510. my ($c0, $r0) = cell_index($not);
  511. my $x_shift;
  512. my $y_shift;
  513. my $n0;
  514. my $ni;
  515. # get y_shift
  516. $y_shift = $mov->[1];
  517. # get x_shift
  518. $x_shift = $mov->[0];
  519. # make x_shift adjustment
  520. $ni = $y_shift != 0 ? ($y_shift / abs($y_shift)) : 1;
  521. $n0 = ($r0 + (($ni + 1)/2) ) % 2;
  522. $x_shift += int(($y_shift + ($n0 * $ni)) / 2);
  523. return apply_shift($not, [$x_shift, $y_shift]);
  524. }
  525. sub get_mov($$){
  526. my ($pi, $en) = (shift, shift);
  527. my @mv1;
  528. @mv1 = grep {
  529. ($_->{"type"} & $en) != 0
  530. } @{$MOVE{$pi}};
  531. return \@mv1;
  532. }
  533. sub find_all_mov($$){
  534. my ($not, $en) = (shift, shift);
  535. my $pi;
  536. my @mv1;
  537. $pi = cell_pi($not);
  538. @mv1 = @{ get_mov($pi, $en) };
  539. return grep {
  540. $_ if $_->[0] ne $ERR_C_1
  541. } map {
  542. [
  543. calc_new_cell($not, $_->{"mov"}),
  544. $_->{"type"}
  545. ]
  546. } @mv1;
  547. }
  548. sub shade_pi_mvmt($$){
  549. my ($not, $en) = (shift, shift);
  550. my $c1;
  551. my @mv1;
  552. @mv1 = find_all_mov($not, $en);
  553. for my $mv (@mv1){
  554. apply_shade($mv->[0], $mv->[1]);
  555. }
  556. }
  557. sub shade_all_mvmt($$){
  558. my ($pl, $en) = (shift, shift);
  559. my @pi1;
  560. # $pl = shift;
  561. @pi1 = grep {
  562. cell_pl($_) eq $pl
  563. } keys(%board);
  564. for my $el (@pi1){
  565. shade_pi_mvmt($el, $en);
  566. }
  567. }
  568. sub shade_all_p1_mvmt($){
  569. shade_all_mvmt($P1, $MOVBLOCK_ENUM);
  570. }
  571. sub get_block_cell($){
  572. my $pl;
  573. $pl = shift;
  574. return map {
  575. $_->[0]
  576. } map {
  577. ( find_all_mov($_, $BLOCK_ENUM) );
  578. } grep {
  579. cell_pl($_) eq $pl
  580. } keys(%board);
  581. }
  582. sub draw($$){
  583. my ($self, $s0) = (shift, shift);
  584. my $i = 0;
  585. for my $s1 (uniq( [split(/ /, $s0)] )){
  586. $i++;
  587. die "invalid card - $s1" unless grep { $_ =~ /^$s1$/ } @MG_PI;
  588. }
  589. die "draw() $s0 - hand size less than $HAND_SIZE. Possible duplicate card?" if $i < $HAND_SIZE;
  590. }
  591. sub new {
  592. my $class = shift;
  593. my $self = { @_ };
  594. # Creates a hash of the the form
  595. # $board{cell_notation} = piece_enum
  596. %board = map {
  597. $_ => $EMPTY_CELL
  598. } map {
  599. my $l0;
  600. $l0 = $_;
  601. (map {$l0.$_} ("1".."11"))
  602. } map {
  603. $AXIS_RV{$_}
  604. }(1...11);
  605. return bless $self, $class;
  606. }
  607. sub uniq($){
  608. my %h0;
  609. return grep { !$h0{$_}++ } @{$_[0]};
  610. }
  611. sub P1 {
  612. return $P1;
  613. }
  614. sub P2 {
  615. return $P2;
  616. }
  617. sub MG_A {
  618. return $MG_A;
  619. }
  620. sub MG_I{
  621. return $MG_I;
  622. }
  623. sub MG_N{
  624. return $MG_N;
  625. }
  626. sub MG_IT{
  627. return $MG_I;
  628. }
  629. sub MG_H{
  630. return $MG_H;
  631. }
  632. sub MG_S{
  633. return $MG_S;
  634. }
  635. sub MG_RC{
  636. return $MG_RO;
  637. }
  638. sub MG_HS{
  639. return $MG_H;
  640. }
  641. sub MG_RO{
  642. return $MG_RC;
  643. }
  644. sub MG_B{
  645. return $MG_B;
  646. }
  647. sub MG_P{
  648. return $MG_P;
  649. }
  650. sub MG_IM{
  651. return $MG_I;
  652. }
  653. sub MG_F{
  654. return $MG_F;
  655. }
  656. sub MG_QS{
  657. return $MG_QS;
  658. }
  659. sub MG_AU{
  660. return $MG_A;
  661. }
  662. sub MG_SY{
  663. return $MG_SY;
  664. }
  665. sub MG_Q{
  666. return $MG_Q;
  667. }
  668. binmode(STDOUT, ":utf8");
  669. return 1;