Une version rudimentaire de Slay The Spire dans le terminal - retour accueil
git clone git://bebou.netlib.re/sts-term
Log | Files | Refs | README |
utils (15828B)
1 #! /bin/sh 2 3 grayed="\x1b[90m" 4 norm="\x1b[0m" 5 6 alias attack=":" 7 alias skill=":" 8 alias status=":" 9 alias curse=":" 10 alias ethereal=":" 11 alias innate=":" 12 13 _getstat() { 14 local target stat 15 target="$1";stat="$2" 16 grep -wF "$2" "$target" | cut -f2 17 } 18 19 power() { 20 local card 21 card="$1" 22 rm -rf $card 23 } 24 25 ##### 26 # UI 27 ##### 28 29 _greyoutnonplayablecards() { 30 find fight/hand -type f | 31 grep -v -f $tmpdir/execcards | 32 xargs -r -n1 basename | sed -E 's/-[0-9]+$//' | 33 while read card;do 34 sed -i -E "/ $card$/ s/^/$grayed/;/$card/ s/$/$norm/" $tmpdir/hand 35 done 36 } 37 38 _createdisplaycard(){ 39 local card name 40 card="$1";name="$(basename $card)" 41 42 <<-. cat > $tmpdir/disp-$name 43 $name 44 45 $(cat $card | 46 grep -Ev "moves|bufs" | 47 sed -E 's/ / : /') 48 49 $(_dispbufsanddebufs $card) 50 51 Next move : 52 53 $(cat $tmpdir/nextmove-$name | tr -d '_') 54 . 55 } 56 57 _dispbufsanddebufs() { 58 local target type 59 target="$1" 60 61 for type in bufs debufs;do 62 echo "$type" 63 grep -E "^$type" $target | 64 cut -sf2- | 65 tr '\t' '\n' | 66 sed 's/ / : /' | 67 column -ts',' 68 done 69 } 70 71 _showplayerstats() { 72 head player -n5 | 73 sed 's/ / : /' | 74 awk '{printf $0"\t";getline;printf $0"\t";getline;printf $0"\t\n"}' | 75 sed -E 's/(gold : [0-9]+).*/\1/' | 76 column -ts' ' 77 } 78 79 _showpileofcards() { 80 local pile 81 pile="$1" 82 tree --noreport fight/$pile | 83 sed -E 's/-[0-9]+$//g; 84 s,fight/,,g' 85 } 86 87 _makeui() { 88 # Pour savoir combien de fois l'ui est rafraichie 89 # Clairement pas optimal mais drôle 90 # #ffplay -nodisp -autoexit -loglevel panic -f lavfi -i "sine=440:d=0.1" 91 [ ! -e "player" ] && printf "No current game\n" 92 93 currentenergy=$(_getstat player energy) 94 _updatecardexecutability 95 96 _showpileofcards stack > $tmpdir/stack 97 _showpileofcards hand > $tmpdir/hand 98 _showpileofcards discard > $tmpdir/discard 99 _showpileofcards exhaust > $tmpdir/exhaust 100 101 _greyoutnonplayablecards 102 103 for c in $(find fight/ennemies -type l) ;do 104 _createdisplaycard "$c" 105 done 106 107 <<-. cat 108 Floor : $(cat fight/floor) 109 Turn : $(cat fight/turn) 110 111 . 112 113 <<-. cat > $tmpdir/left-pane 114 $(_showplayerstats) 115 116 $(_dispbufsanddebufs player) 117 118 $(paste $tmpdir/disp-* | column -ts' ') 119 120 $(paste $tmpdir/stack $tmpdir/discard $tmpdir/exhaust | column -ts' ') 121 . 122 123 paste $tmpdir/left-pane $tmpdir/hand | 124 column -ts' ' 125 } 126 127 ##### 128 # 129 #### 130 131 _makefight() { 132 rm -rf fight 133 134 mkdir -p fight/ennemies 135 mkdir -p fight/stack 136 mkdir -p fight/hand 137 mkdir -p fight/discard 138 mkdir -p fight/exhaust 139 140 echo "1" > fight/turn 141 basename "$1" > fight/floor 142 143 cp deck/* fight/stack 144 145 for en in $(find "$1" -type f);do 146 ln -rs -f "$en" fight/ennemies/$(basename "$en") 147 done 148 149 ln -rs -f player fight/player 150 _setstat fight/player block 0 151 grep -EH "^innate" deck/* | 152 cut -d: -f1 | 153 while read card;do 154 echo "drawing innate $(basename $card)" 155 _draw 1 "$(basename $card)" 156 done 157 remcards="$(( 5 - $(find fight/hand -type f | wc -l) ))" 158 echo _draw "$remcards" 159 _draw "$remcards" 160 _setstat fight/player energy 3 161 _createnextmoves 162 _refreshUI 163 } 164 165 _exhaust() { 166 local card 167 card="$1" 168 echo "$card" | grep -q 'sentinel' && 169 _changestat player energy +2 170 _hasstatus player dark-embrace && _draw 1 171 _hasstatus player feel-no-pain && { echo "gaining block from feel no pain"; _defend $(_getremainingstatusturns player feel-no-pain) player; } 172 echo mv "$card" fight/exhaust 173 mv "$card" fight/exhaust 174 } 175 176 _dupcard() { 177 local card dest howmuch 178 card="$2";dest="$3";howmuch="$1" 179 name="$(basename $card | sed -E 's/-[0-9]+$//')" 180 nbcard=$(find deck -name "$name-*" | wc -l) 181 echo "duplicating card $card instance of $name $howmuch times starting from id $(( $nbcard + 1 ))" 182 for i in $(seq $(( $nbcard + 1 )) $(( $nbcard + $howmuch )));do 183 cp $card $dest/$name-$i 184 done 185 } 186 187 _addcard() { 188 local howmuch name dest nbcard location 189 howmuch="$1";name="$2";dest="${3:-deck}" 190 nbcard=$(find deck -name "$2-*" | wc -l) 191 location=$(find bdd/cards -type f -name "$name") 192 for i in $(seq $(( $nbcard + 1 )) $(( $nbcard + $howmuch )));do 193 echo "adding card $name nb $i in $dest" 194 if [ "$name" = "wounds" ];then 195 cp bdd/cards/statuses/$name $dest/$name-$i 196 else 197 <<-. cat > $tmpdir/A 198 . ./utils 199 $(cat "$location" | 200 sed -E '/^[ ]*_(cost|defend) / s/$/ player/; 201 /^[ ]*_(attack|status) / s/$/ "${1:?need a target}" fight\/player "$0"/; 202 /^[ ]*_(heal) / s/$/ "$0"/; 203 /^power/ s/$/ "\$0"/ 204 /^[ ]*_exhaust$/ s/$/ "$0"/') 205 _discard "\$0" 206 _refreshUI 207 . 208 mv $tmpdir/A $dest/$name-$i 209 fi 210 done 211 } 212 213 _hasrelic() { 214 name="$1" 215 return $([ -e "relics/$1" ]) 216 } 217 218 _wingold() { 219 currentgold=$(_getstat player gold) 220 _setstat player gold "$(( $currentgold + $(seq 10 20 | shuf | head -n1) ))" 221 } 222 223 _killennemie() { 224 local target card name 225 target="$1";card="${2:-something else}" 226 name="$(basename $target)" 227 echo "killed ennemie $target with card $card" 228 echo rm -rf "$(readlink -e $target)" 229 echo "$card" | grep -q "/feed-" && _changestat player maxhealth +3; 230 rm -rf "$(readlink -e $target)" 231 rm -rf "$target" 232 find $tmpdir -name "*$name*" | 233 xargs rm -rf 234 if [ $(find fight/ennemies -type l | wc -l) = '0' ];then 235 echo "end of combat" 236 _hasrelic burning-blood && _heal +6 237 _wingold 238 _refreshUI 239 _choosecard 240 _makefight map/$(( $(cat fight/floor) + 1 )) 241 exit 0 242 fi 243 } 244 245 # modifie d'une valeur relative 246 # value doit avoir l'opérateur (+3, -3, *3) 247 _changestat() { 248 local target stat value card 249 target="$1";stat="$2";value="$3";card="$4" 250 [ "$target" = "all" ] && { 251 target=$(find fight/ennemies -type l);} 252 echo "$target" | while read t;do 253 curvalue=$(_getstat "$t" "$stat") 254 _setstat "$t" "$stat" $(( $curvalue $value )) "$card" 255 done 256 } 257 258 # set la valeur absolue 259 _setstat() { 260 local target stat value card 261 target="$1";stat="$2";value="$3";card="$4" 262 if [ "$stat" = "health" -a "$value" -le '0' ];then 263 case "$target" in 264 ("*player*") _gameover;; 265 (*) _killennemie "$target" "$card";; 266 esac 267 fi 268 [ "$stat" = "block" ] && [ "$value" -gt "0" ] && _hasstatus player juggernaut && 269 _dodamage $(_getremainingstatusturns player juggernaut) $(_randomennemy) player 270 echo sed -i --follow-symlinks -E "/^$stat / s/ .*/ $value/" "$target" 271 sed -i --follow-symlinks -E "/^$stat / s/ .*/ $value/" "$target" 272 } 273 274 _gameover() { 275 echo "game over" | toilet -f ansi > UI 276 sleep 2 277 ./reset 278 } 279 280 _decrbfbcost() { 281 find fight -name '*blood-for-blood*' | 282 while read card;do 283 curcost=$(grep cost "$card" | cut -d' ' -f2) 284 sed -i -E "/_cost/ s/[0-9]/$(( $curcost - 1 ))/" "$card" 285 done 286 } 287 288 _dodamage() { 289 #ffplay -nodisp -autoexit -loglevel panic -i sounds/hit.ogg 290 local damage target hitter card targetblock targethealth newblock str; 291 damage="$1";target="$2";hitter="$3";card="$4" 292 echo "$target" | grep -q "player" && _decrbfbcost 293 $(echo "$target" | grep -q "player") && $(echo "$hitter" | grep -vq "player") && $(_hasstatus player flame-barrier) && { 294 echo returning damage : _dodamage $(_getremainingstatusturns player flame-barrier) "$hitter" player; 295 _dodamage $(_getremainingstatusturns player flame-barrier) "$hitter" player; } 296 echo "$target" | grep -q "player" && _decrbfbcost 297 targethealth=$(_getstat "$target" health);targetblock=$(_getstat "$target" block) 298 _hasstatus "$hitter" strength && str=$(_getremainingstatusturns "$hitter" strength) || str='0' 299 echo "using card $card" 300 echo "$card" | grep -q "heavy-blade" && str=$(( str*3 )) 301 _hasstatus "$hitter" weak && multiplier=0.75 || multiplier=1 302 _hasstatus "$target" vulnerable && multiplier=$(echo "$multiplier*1.5" | bc -l) 303 echo "($targetblock - ($damage+$str)*$multiplier)/1" 304 newblock=$(echo "($targetblock - ($damage+$str)*$multiplier)/1" | bc) 305 # Si la quantité de block qui reste est négative c'est qu'on prend cette 306 # quantité de dégât 307 # On remet le block à 0 308 [ "$newblock" -lt '0' ] && { 309 echo _changestat "$target" health "$newblock" "$card"; 310 echo "$card" | grep -q "reaper-*" && 311 _heal $(($newblock*-1)) "$card" 312 _changestat "$target" health "$newblock" "$card"; 313 newblock=0 ;} 314 echo _setstat "$target" block "$newblock" 315 _setstat "$target" block "$newblock" 316 } 317 318 _attack() { 319 local damage times target hitter card 320 damage="$1";times="$2";target="$3";hitter="$4";card="$5" 321 _hasstatus player rage && 322 _changestat player block "+$(_getremainingstatusturns player rage)" 323 [ "$target" = "all" ] && { 324 echo "attacking multiple ennemies"; 325 target=$(find fight/ennemies -type l); 326 hitter="$5";card="$6";} 327 echo "$target" | 328 while read t;do 329 echo "damaging ennemie $t $times times with $damage damage" 330 for i in $(seq $times);do 331 echo _dodamage "$damage" "$t" "$hitter" 332 _dodamage "$damage" "$t" "$hitter" "$card" 333 done; 334 done 335 } 336 337 _defend() { 338 local block target 339 block="$1";target="$2" 340 echo _changestat "$target" block "+$block" 341 _changestat "$target" block "+$block" 342 } 343 344 _updatecardexecutability() { 345 currentenergy=$(_getstat player energy) 346 grep -EH "^_cost" fight/hand/* | 347 awk "\$2<=$currentenergy{print}" | 348 cut -d':' -f1 | 349 xargs -r chmod +x 350 351 grep -EH "^_cost" fight/hand/* | 352 awk "\$2>$currentenergy{print}" | 353 cut -d':' -f1 | 354 xargs -r chmod -x 355 356 nbcard=$(find fight/hand -type f | wc -l) 357 nbattacks=$(grep "^attack" fight/hand/* | wc -l) 358 [ ! "$nbcard" = "$nbattack" ] && [ -e "fight/hand/clash-1" ] && 359 chmod -x fight/hand/clash-* 360 361 find fight/hand -type f -executable | xargs -r -n1 basename > $tmpdir/execcards 362 363 } 364 365 _cost() { 366 local cost 367 cost="$1" 368 currentenergy=$(_getstat player energy) 369 newenergy=$(( $currentenergy - $cost )) 370 _setstat fight/player energy "$newenergy" 371 } 372 373 _shufflediscard() { 374 mv fight/discard/* fight/stack 375 } 376 377 _choosecard() { 378 find bdd/cards/red -type f | 379 grep -Ev '(strike|defend|bash)$' | 380 shuf | 381 head -n3 | 382 xargs -n1 basename | 383 sed '$ a\skip' | 384 fzy | 385 while read card;do 386 [ "$card" = "skip" ] && break 387 _addcard 1 "$card" 388 done 389 } 390 391 _nodraw () { 392 echo 393 } 394 395 _heal() { 396 local amount src 397 amount="$1";src="$2" 398 maxhealth=$(_getstat player maxhealth) 399 [ "$amount" -lt "0" ] \ 400 && echo "$src" | grep -q "fight/hand" \ 401 && _hasstatus player rupture && 402 _strength "1" player 403 newhealth=$(( $(_getstat player health | cut -f2) + $amount )) 404 echo _setstat fight/player health $(( $newhealth > $maxhealth ? $maxhealth : $newhealth )) 405 _setstat fight/player health $(( $newhealth > $maxhealth ? $maxhealth : $newhealth )) 406 } 407 408 _exetherealcard() { 409 grep -HE '^ethereal' fight/hand/* | 410 cut -d: -f1 | 411 while read card;do _exhaust "$card"; done 412 } 413 414 endturn() { 415 _exetherealcard 416 for e in $(find fight/ennemies -type l);do 417 _setstat $e block 0 418 done 419 _hasstatus player metallicize && 420 _defend $(_getremainingstatusturns player metallicize) player 421 _hasstatus player combust && { 422 v="$(_getremainingstatusturns player combust)" 423 _heal "-$v" fight/hand 424 for i in $(find fight/ennemies -type l);do _dodamage $((5*$v)) $i player;done ;} 425 _execnextmove 426 _hasstatus player demon-form && 427 _status strength $(_getremainingstatusturns player demon-form) player 428 [ $(find fight/hand -name 'burn-*' | wc -l) -gt '0' ] && 429 chmod +x fight/hand/burn-*;find fight/hand -name 'burn-*' | sh 430 _hasstatus player barricade || 431 _setstat fight/player block 0 432 _setstat fight/player energy 3 433 _hasstatus player berserk && 434 _changestat player energy "+$(_getremainingstatusturns player berserk)" 435 _hasstatus player strength-down && { 436 _status strength "-$(_getremainingstatusturns player strength-down)" player; 437 _removestatus player strength-down; } 438 _decreasestatuses 439 _removestatus player flame-barrier 440 _removestatus player rage 441 _createnextmoves 442 _newhand 443 _hasstatus player brutality && { 444 _heal -3 fight/hand; 445 _draw 1; } 446 echo "$(( $(cat fight/turn) + 1 ))" > fight/turn 447 _refreshUI 448 } 449 450 _draw() { 451 local nbtodraw card 452 _hasstatus player no-draw && return 0 453 nbtodraw="$1";innatecard="$2" 454 for nb in $(seq "$nbtodraw");do 455 [ "$(find fight/stack -type f | wc -l)" = "0" ] && _shufflediscard 456 [ -z "$innatecard" ] \ 457 && card=$(find fight/stack -type f | shuf | head -n 1) \ 458 || card="fight/stack/$innatecard" 459 chmod +x "$card" 460 cardtype=$(sed -n '2 p' "$card") 461 echo mv "$card" fight/hand of type $cardtype 462 mv "$card" fight/hand 463 _hasstatus player fire-breathing && [ "$cardtype" = "status" -o "$cardtype" = "curse" ] && { 464 v=$(_getremainingstatusturns player fire-breathing); 465 for i in $(find fight/ennemies -type l);do _dodamage $v $i player;done ;} 466 _hasstatus player evolve && [ "$cardtype" = "$status" ] && 467 _draw 1 468 done 469 } 470 471 _newhand() { 472 local nb 473 nb="${1:-5}" 474 find fight/hand -type f | 475 while read card;do 476 _discard "$card" 477 done 478 _draw $nb 479 } 480 481 _discard() { 482 card="$1" 483 [ -e "$card" ] && { 484 chmod -x "$card"; 485 mv "$card" fight/discard;} 486 } 487 488 _refreshUI() { 489 _makeui > UI 490 } 491 492 ##### 493 # Statuses 494 ##### 495 496 _status() { 497 local stat nbturns target 498 stat="$1";nbturns="$2";target="$3" 499 case "$stat" in 500 (vulnerable|weak|strength-down) type="debufs";; 501 (*) type="bufs";; 502 esac 503 [ "$target" = "all" ] && 504 target=$(find fight/ennemies -type l) 505 echo "$target" | while read t;do 506 if $(_hasstatus "$t" "$stat");then 507 remturn=$(_getremainingstatusturns "$t" "$stat") 508 totturns=$(( $nbturns + ${remturn:-0} )) 509 if [ "$totturns" = "0" ];then 510 _removestatus "$t" "$stat" 511 else 512 echo sed --follow-symlinks -i -E "/^$type/ s/$stat,-?[0-9]+/$stat,$totturns/" "$t" 513 sed --follow-symlinks -i -E "/^$type/ s/$stat,-?[0-9]+/$stat,$totturns/" "$t" 514 fi 515 else 516 echo sed --follow-symlinks -i -E "/^$type/ s/$/ $stat,$nbturns/" "$t" 517 [ "$stat" = "corruption" ] && { 518 grep -rH "^skill" fight | cut -d':' -f1 | 519 xargs -r sed -i -E '/^_cost/ s/[0-9]/0/; 520 /^_discard/ i\_exhaust "$0"'; 521 _updatecardexecutability;} 522 sed --follow-symlinks -i -E "/^$type/ s/$/ $stat,$nbturns/" "$t" 523 fi 524 done 525 } 526 527 _getstatuses() { 528 local target 529 target="$1" 530 grep -E '^(de)?bufs ' "$target" | 531 cut -f2- | 532 tr ' ' '\n' | 533 grep -Ev '(strength|dark-embrace|feel-no-pain|metallicize|rupture|barricade|berserk|brutality|demon-form|juggernaut|combust|corruption|evolve|fire-breathing)' | 534 cut -d',' -f1 535 } 536 537 _decreasestatuses() { 538 statuses=$(_getstatuses player) 539 if [ ! -z "$statuses" ];then 540 echo "$statuses" | 541 while read stat;do 542 _status "$stat" -1 player 543 done 544 fi 545 find fight/ennemies/* -type l | 546 while read ennemy;do 547 statuses=$(_getstatuses "$ennemy") 548 [ -z "$statuses" ] && continue 549 echo "$statuses" | 550 while read stat;do 551 _status "$stat" -1 "$ennemy" 552 done 553 done 554 } 555 556 _hasstatus() { 557 local target stat 558 target="${1:?need target}";stat="$2" 559 grep -Eq "^(de)?bufs.*$stat,-?[0-9]+" "$target" 560 } 561 562 _getremainingstatusturns() { 563 local target stat 564 target="$1";stat="$2" 565 grep -Eo " $stat,-?[0-9]+" "$target" | cut -d',' -f2 566 } 567 568 _removestatus() { 569 local target stat 570 target="$1" 571 stat="$2" 572 sed -i -E --follow-symlinks "/^(de)?bufs/ s/ $stat,[0-9]+//" "$target" 573 } 574 575 ##### 576 # Ennemies 577 ##### 578 579 _createnextmoves() { 580 581 find fight/ennemies/ -type l | 582 while read en;do 583 id=$(basename $en) 584 grep moves "$en" | 585 cut -f2- | 586 tr ' ' '\n' | 587 shuf | head -n1 | 588 tr ',' ' ' | tr ';' '\n' > $tmpdir/nextmove-$id 589 <<-. cat > $tmpdir/executablenextmove-$id 590 . ./utils 591 $(< $tmpdir/nextmove-$id sed -E "/attack/ s,$, fight/player $en,;/defend/ s,$, $en,") 592 . 593 done 594 595 chmod +x $tmpdir/executablenextmove-* 596 } 597 598 _execnextmove() { 599 echo $tmpdir/executablenextmove-* | 600 tr ' ' ';' | 601 sh 602 } 603 604 #### 605 # Cards 606 #### 607 # Les fonctions appelées pas les cartes 608 609 _strength() { 610 local value target 611 value="$1";target="$2" 612 _status strength "$value" "$target" 613 } 614 615 ##### 616 # Interaction 617 ##### 618 619 choice() { 620 c=$(find fight/hand -type f | fzy) 621 $(echo "$c" | grep -Eq "(defend|shrug-it-off)") && { eval $c; return 0; } 622 t=$(find fight/ennemies -type l | fzy) 623 _hasstatus player double-tap \ 624 && cat "$c" | grep -q '^_attack' && { 625 < $c sed -E '/^_cost/ s/[0-9]/0/ 626 /^_discard/ s/.*/rm -rf "$0"/' > $tmpdir/doubled; 627 chmod +x $tmpdir/doubled; 628 eval $tmpdir/doubled $t; 629 _status double-tap -1 player; } 630 eval $c $t 631 }