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.

903 rindas
21KB

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