Implementation of Lucifers Pastime
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

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