Compare commits

...

38 Commits

Author SHA1 Message Date
VS-Code
86b537e3eb Chess_update 2026-02-25 11:11:21 +01:00
VS-Code
3be3030a37 Chess_update 2026-02-25 10:45:11 +01:00
VS-Code
bbe3a648fb added Figures 2026-02-14 15:29:12 +01:00
VS-Code
0ba7a7c8a0 - 2026-02-14 14:13:25 +01:00
VS-Code
46d9d142e8 Update-Chess 2026-02-12 16:44:26 +01:00
VS-Code
b6e36aa2dc Chess-update 2026-02-11 17:22:11 +01:00
VS-Code
b5f608ce66 Update-Chess 2026-02-10 16:23:16 +01:00
VS-Code
f1d1f436af Chess-Update 2026-02-09 16:21:00 +01:00
VS-Code
cb2e2ba210 Chess-Update 2026-02-09 15:05:17 +01:00
VS-Code
a0435cdd57 - 2026-02-06 22:36:46 +01:00
VS-Code
2539fe5b92 - 2026-02-06 22:33:34 +01:00
VS-Code
468d7d9a35 - 2026-02-06 22:30:18 +01:00
VS-Code
da8752c22a - 2026-02-06 22:28:34 +01:00
VS-Code
13d0de4cc9 - 2026-02-06 22:28:08 +01:00
VS-Code
c264362f50 - 2026-02-06 22:21:57 +01:00
VS-Code
a5f1740d81 add icon 2026-02-06 22:20:11 +01:00
VS-Code
715cda4e41 added games 2026-02-06 22:14:01 +01:00
VS-Code
ed39f9ae04 fixed ugly 2026-02-06 16:05:21 +01:00
VS-Code
d4f406609a - 2026-02-06 16:04:26 +01:00
VS-Code
2c8dac3cdd - 2026-02-06 16:02:09 +01:00
VS-Code
2a8933e5ee - 2026-02-06 16:00:26 +01:00
VS-Code
192296cfca - 2026-02-06 15:59:49 +01:00
VS-Code
c0ff8c2b2e - 2026-02-06 15:58:53 +01:00
VS-Code
02582dee4a .- 2026-02-06 15:57:55 +01:00
VS-Code
f6bc5eead1 - 2026-02-06 15:57:03 +01:00
VS-Code
4978c5c9b4 - 2026-02-06 15:53:20 +01:00
VS-Code
addc23bc14 Animations 2026-02-06 15:51:37 +01:00
VS-Code
986a513138 - 2026-02-06 15:47:04 +01:00
VS-Code
744e458d7b - 2026-02-06 15:43:16 +01:00
VS-Code
e4cca61b82 - 2026-02-06 15:39:07 +01:00
VS-Code
8c6b465f4c beautyfied 2026-02-06 15:34:00 +01:00
VS-Code
b0afaed73e - 2026-02-06 15:28:21 +01:00
VS-Code
e166257f57 added Teminal Look HELIOS 2026-02-06 15:25:18 +01:00
VS-Code
66bd99b035 - 2026-02-06 15:16:39 +01:00
VS-Code
a3cc5b9463 fix index.html 2026-02-06 15:15:48 +01:00
VS-Code
d858d57752 fix | index.hmtl top-bar 2026-02-06 13:35:09 +01:00
VS-Code
c726b3e1e6 changed chess to chess_64 2026-02-06 13:23:45 +01:00
VS-Code
be15051395 fix | landingpage nav-bar 2026-02-06 13:17:51 +01:00
5 changed files with 1838 additions and 190 deletions

View File

@@ -1,18 +1,698 @@
type_to_name = [] from cmd import PROMPT
import os
# region Constants
# White Constants
W_KIN, W_QUE, W_BIS, W_NHT, W_ROO, W_PAW = range(6)
# Black Constans
B_KIN, B_QUE, B_BIS, B_NHT, B_ROO, B_PAW = range(6,12)
# Turn Constants
WHITE, BLACK = 0, 1
# Piece Constants
KIN, QUE, BIS, NHT, ROO, PAW = range(6)
NO_PIECE = 15
class COL():
FG_WHITE = "\033[38;5;253m"
FG_BLACK = "\033[38;5;232m"
BG_WHITE = "\033[48;5;230m"
BG_DARK = "\033[48;5;71m"
BG_MOVE = "\033[48;5;249m"
RESET = "\033[0m"
PIECE_TO_STR = ["wK", "wQ", "wB", "wN", "wR", "wP",
"bK", "bQ", "bB", "bN", "bR", "bP"]
PIECE_TO_SYM = ["", "", "", "", "", "",
"", "", "", "", "", ""]
# Square Constants
A8, B8, C8, D8, E8, F8, G8, H8 = range(56, 64)
A7, B7, C7, D7, E7, F7, G7, H7 = range(48, 56)
A6, B6, C6, D6, E6, F6, G6, H6 = range(40, 48)
A5, B5, C5, D5, E5, F5, G5, H5 = range(32, 40)
A4, B4, C4, D4, E4, F4, G4, H4 = range(24, 32)
A3, B3, C3, D3, E3, F3, G3, H3 = range(16, 24)
A2, B2, C2, D2, E2, F2, G2, H2 = range(8, 16)
A1, B1, C1, D1, E1, F1, G1, H1 = range(8)
# Convert Piece to number
PCE_TO_NUM = {"K":0, "Q":1, "B":2, "N":3, "R":4, "P":5}
# Convert Field to index
STR_TO_SQ = {}
files = "ABCDEFGH" # Oder "abcdefgh" je nach UCI Standard
ranks = "12345678"
for r_idx, r in enumerate(ranks):
for f_idx, f in enumerate(files):
# Berechne Index (Little Endian: A1=0, B1=1 ... H8=63)
sq = r_idx * 8 + f_idx
key = f + r # z.B. "A1"
STR_TO_SQ[key] = sq
# Move Flags
QUIET = 0
DOUBLE_PAWN_PUSH = 1
KING_CASTLE = 2
QUEEN_CASTLE = 3
CAPTURE = 4
EP_CAPTURE = 5
# Falls Capture +4 (z.B. BIS Capture -> 13)
PROMO_KNIGHT = 8
PROMO_BISHOP = 9
PROMO_ROOK = 10
PROMO_QUEEN = 11
# Masks
NOT_A = 0xfefefefefefefefe
NOT_H = 0x7f7f7f7f7f7f7f7f
NOT_AB = 0xfcfcfcfcfcfcfcfc
NOT_GH = 0x3f3f3f3f3f3f3f3f
FULL_MASK = 0xffffffffffffffff
# Attacks Movesets & Rays
KIN_ATTACKS = [0] * 64
NHT_ATTACKS = [0] * 64
PAW_ATTACKS = [0] * 128 # 0-63 für Weiße Bauern, 64-127 für Schwarze Bauern
RAYS_N = [0] * 64
RAYS_NE = [0] * 64
RAYS_E = [0] * 64
RAYS_SE = [0] * 64
RAYS_S = [0] * 64
RAYS_SW = [0] * 64
RAYS_W = [0] * 64
RAYS_NW = [0] * 64
clear = lambda: os.system('clear')
# endregion
class Bitboard():
def __init__(self) -> None:
# WHITE 0:King, 1:Queen, 2:Bishop, 3:Knight, 4:Rook, 5:Pawn
# BLACK 6:King, 7:Queen, 8:Bishop, 9:Knight, 10:Rook, 11:Pawn
self.bitboards = [0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0]
self.side_to_move = WHITE
self.playing = True
self.bitboards[W_KIN] = 1 << E1
self.bitboards[W_QUE] = 1 << D1
self.bitboards[W_BIS] = (1 << C1) | (1 << F1)
self.bitboards[W_NHT] = (1 << B1) | (1 << G1)
self.bitboards[W_ROO] = (1 << A1) | (1 << H1)
self.bitboards[W_PAW] = 0xFF << 8
self.bitboards[B_KIN] = 1 << E8
self.bitboards[B_QUE] = 1 << D8
self.bitboards[B_BIS] = (1 << C8) | (1 << F8)
self.bitboards[B_NHT] = (1 << B8) | (1 << G8)
self.bitboards[B_ROO] = (1 << A8) | (1 << H8)
self.bitboards[B_PAW] = 0xFF << 48
self.all_pieces = [0, 0]
self.all_pieces[0] = self.bitboards[W_KIN] | self.bitboards[W_QUE] | self.bitboards[W_BIS] | self.bitboards[W_NHT] | self.bitboards[W_ROO] | self.bitboards[W_PAW]
self.all_pieces[1] = self.bitboards[B_KIN] | self.bitboards[B_QUE] | self.bitboards[B_BIS] | self.bitboards[B_NHT] | self.bitboards[B_ROO] | self.bitboards[B_PAW]
self.move_list = []
def get_all_moves(self):
moves = []
captures = []
turn = self.side_to_move
opp = turn ^ 1
turn_offset = turn * 6
opp_offset = opp *6
# region import self & global Varibles for speed optimization
bbs = self.bitboards
opponent_pcs = self.all_pieces[opp]
friendly_pcs = self.all_pieces[turn]
occupancy = opponent_pcs | friendly_pcs
kin, que, bis, nht, roo, paw, no_piece = KIN, QUE, BIS, NHT, ROO, PAW, NO_PIECE
nht_attacks_list, paw_attacks_list = NHT_ATTACKS, PAW_ATTACKS
quiet, dpp, k_castle, q_castle, capture, ep_capture = QUIET, DOUBLE_PAWN_PUSH, KING_CASTLE, QUEEN_CASTLE, CAPTURE, EP_CAPTURE
promo_knight, promo_bishop, promo_rook, promo_queen = PROMO_KNIGHT, PROMO_BISHOP, PROMO_ROOK, PROMO_QUEEN
rays_n, rays_ne, rays_e, rays_se, rays_s, rays_sw, rays_w, rays_nw = RAYS_N, RAYS_NE, RAYS_E, RAYS_SE, RAYS_S, RAYS_SW, RAYS_W, RAYS_NW
# endregion
# region --- King Moves ---
kin_sq = bbs[kin + turn_offset].bit_length() - 1
kin_attacks = KIN_ATTACKS[kin_sq]
kin_attacks &= ~friendly_pcs
while kin_attacks:
to_sq = (kin_attacks & -kin_attacks).bit_length() - 1
to_mask = 1 << to_sq
kin_attacks &= (kin_attacks - 1)
if to_mask & opponent_pcs:
if to_mask & bbs[paw + opp_offset]:
captured = paw + opp_offset
elif to_mask & bbs[nht + opp_offset]:
captured = nht + opp_offset
elif to_mask & bbs[bis + opp_offset]:
captured = bis + opp_offset
elif to_mask & bbs[roo + opp_offset]:
captured = roo + opp_offset
else:
captured = que + opp_offset
captures.append(to_sq | (kin_sq << 6) | ((kin + turn_offset) << 12) | (captured << 16) | capture << 20)
else:
moves.append(to_sq | (kin_sq << 6) | ((kin + turn_offset) << 12) | (no_piece << 16) | quiet << 20)
# endregion
# region --- Knight Moves ---
nht_bb = bbs[nht + turn_offset]
while nht_bb:
nht_sq = (nht_bb & -nht_bb).bit_length() - 1
nht_bb &= (nht_bb - 1)
nht_attacks = nht_attacks_list[nht_sq]
nht_attacks &= ~friendly_pcs
while nht_attacks:
to_sq = (nht_attacks & -nht_attacks).bit_length() - 1
to_mask = 1 << to_sq
nht_attacks &= (nht_attacks - 1)
if to_mask & opponent_pcs:
if to_mask & bbs[paw + opp_offset]:
captured = paw + opp_offset
elif to_mask & bbs[nht + opp_offset]:
captured = nht + opp_offset
elif to_mask & bbs[bis + opp_offset]:
captured = bis + opp_offset
elif to_mask & bbs[roo + opp_offset]:
captured = roo + opp_offset
else:
captured = que + opp_offset
captures.append(to_sq | (nht_sq << 6) | ((nht + turn_offset) << 12) | (captured << 16) | capture << 20)
else:
moves.append(to_sq | (nht_sq << 6) | ((nht + turn_offset) << 12) | (no_piece << 16) | quiet << 20)
# endregion
# region --- Pawn Moves ---
paw_bb = bbs[paw + turn_offset]
while paw_bb:
paw_sq = (paw_bb & -paw_bb).bit_length() - 1
paw_bb &= (paw_bb -1)
paw_attacks = paw_attacks_list[paw_sq + turn_offset]
# Irgendwann noch En Passant einfügen
paw_attacks &= opponent_pcs
while paw_attacks:
flag = capture
to_sq = (paw_attacks & -paw_attacks).bit_length() - 1
to_mask = 1 << to_sq
paw_attacks &= (paw_attacks - 1)
if to_mask & bbs[paw + opp_offset]:
captured = paw + opp_offset
elif to_mask & bbs[nht + opp_offset]:
captured = nht + opp_offset
elif to_mask & bbs[bis + opp_offset]:
captured = bis + opp_offset
elif to_mask & bbs[roo + opp_offset]:
captured = roo + opp_offset
else:
captured = que + opp_offset
captures.append(to_sq | (paw_sq << 6) | ((paw + turn_offset) << 12) | (captured << 16) | flag << 20)
if turn == 0:
to_sq = paw_sq + 8
to_mask = 1 << to_sq
if not to_mask & occupancy:
moves.append(to_sq | (paw_sq << 6) | ((paw + turn_offset) << 12) | (no_piece << 16) | quiet << 20)
if 8 <= paw_sq <= 15:
to_sq_push = paw_sq + 16
to_mask_push = 1 << to_sq_push
if not to_mask_push & occupancy:
moves.append(to_sq_push | (paw_sq << 6) | ((paw + turn_offset) << 12) | (no_piece << 16) | dpp << 20)
else:
to_sq = paw_sq - 8
to_mask = 1 << to_sq
if not to_mask & occupancy:
moves.append(to_sq | (paw_sq << 6) | ((paw + turn_offset) << 12) | (no_piece << 16) | quiet << 20)
if 48 <= paw_sq <= 55:
to_sq_push = paw_sq - 16
to_mask_push = 1 << to_sq_push
if not to_mask_push & occupancy:
moves.append(to_sq_push | (paw_sq << 6) | ((paw + turn_offset) << 12) | (no_piece << 16) | dpp << 20)
# endregion Pawn Moves
# region --- Bishop Moves ---
bis_bb = bbs[bis + turn_offset]
while bis_bb:
bis_sq = (bis_bb & -bis_bb).bit_length() - 1
bis_bb &= (bis_bb - 1)
# region North-East
ray = rays_ne[bis_sq]
blockers = ray & occupancy
if blockers:
blocker_sq = (blockers & -blockers).bit_length() - 1
ray_to_del = rays_ne[blocker_sq]
bis_attacks = (ray ^ ray_to_del) & ~friendly_pcs
else:
bis_attacks = ray
while bis_attacks:
to_sq = (bis_attacks & -bis_attacks).bit_length() - 1
to_mask = 1 << to_sq
bis_attacks &= (bis_attacks - 1)
if to_mask & opponent_pcs:
if to_mask & bbs[paw + opp_offset]:
captured = paw + opp_offset
elif to_mask & bbs[nht + opp_offset]:
captured = nht + opp_offset
elif to_mask & bbs[bis + opp_offset]:
captured = bis + opp_offset
elif to_mask & bbs[roo + opp_offset]:
captured = roo + opp_offset
else:
captured = que + opp_offset
captures.append(to_sq | (bis_sq << 6) | ((bis + turn_offset) << 12) | (captured << 16) | capture << 20)
else:
moves.append(to_sq | (bis_sq << 6) | ((bis + turn_offset) << 12) | (no_piece << 16) | quiet << 20)
# endregion
# region North-West
ray = rays_nw[bis_sq]
blockers = ray & occupancy
if blockers:
blocker_sq = (blockers & -blockers).bit_length() - 1
ray_to_del = rays_nw[blocker_sq]
bis_attacks = (ray ^ ray_to_del) & ~friendly_pcs
else:
bis_attacks = ray
while bis_attacks:
to_sq = (bis_attacks & -bis_attacks).bit_length() - 1
to_mask = 1 << to_sq
bis_attacks &= (bis_attacks - 1)
if to_mask & opponent_pcs:
if to_mask & bbs[paw + opp_offset]:
captured = paw + opp_offset
elif to_mask & bbs[nht + opp_offset]:
captured = nht + opp_offset
elif to_mask & bbs[bis + opp_offset]:
captured = bis + opp_offset
elif to_mask & bbs[roo + opp_offset]:
captured = roo + opp_offset
else:
captured = que + opp_offset
captures.append(to_sq | (bis_sq << 6) | ((bis + turn_offset) << 12) | (captured << 16) | capture << 20)
else:
moves.append(to_sq | (bis_sq << 6) | ((bis + turn_offset) << 12) | (no_piece << 16) | quiet << 20)
# endregion
# region South-East
ray = rays_se[bis_sq]
blockers = ray & occupancy
if blockers:
blocker_sq = blockers.bit_length() - 1
ray_to_del = rays_se[blocker_sq]
bis_attacks = (ray ^ ray_to_del) & ~friendly_pcs
else:
bis_attacks = ray
while bis_attacks:
to_sq = (bis_attacks & -bis_attacks).bit_length() - 1
to_mask = 1 << to_sq
bis_attacks &= (bis_attacks - 1)
if to_mask & opponent_pcs:
if to_mask & bbs[paw + opp_offset]:
captured = paw + opp_offset
elif to_mask & bbs[nht + opp_offset]:
captured = nht + opp_offset
elif to_mask & bbs[bis + opp_offset]:
captured = bis + opp_offset
elif to_mask & bbs[roo + opp_offset]:
captured = roo + opp_offset
else:
captured = que + opp_offset
captures.append(to_sq | (bis_sq << 6) | ((bis + turn_offset) << 12) | (captured << 16) | capture << 20)
else:
moves.append(to_sq | (bis_sq << 6) | ((bis + turn_offset) << 12) | (no_piece << 16) | quiet << 20)
# endregion
# region South-West
ray = rays_sw[bis_sq]
blockers = ray & occupancy
if blockers:
blocker_sq = blockers.bit_length() - 1
ray_to_del = rays_sw[blocker_sq]
bis_attacks = (ray ^ ray_to_del) & ~friendly_pcs
else:
bis_attacks = ray
while bis_attacks:
to_sq = (bis_attacks & -bis_attacks).bit_length() - 1
to_mask = 1 << to_sq
bis_attacks &= (bis_attacks - 1)
if to_mask & opponent_pcs:
if to_mask & bbs[paw + opp_offset]:
captured = paw + opp_offset
elif to_mask & bbs[nht + opp_offset]:
captured = nht + opp_offset
elif to_mask & bbs[bis + opp_offset]:
captured = bis + opp_offset
elif to_mask & bbs[roo + opp_offset]:
captured = roo + opp_offset
else:
captured = que + opp_offset
captures.append(to_sq | (bis_sq << 6) | ((bis + turn_offset) << 12) | (captured << 16) | capture << 20)
else:
moves.append(to_sq | (bis_sq << 6) | ((bis + turn_offset) << 12) | (no_piece << 16) | quiet << 20)
# endregion
# endregion Bishop Moves
# region --- Rook Moves ---
roo_bb = bbs [roo + turn_offset]
while roo_bb:
roo_sq = (roo_bb & -roo_bb).bit_length() -1
roo_bb &= (roo_bb -1)
# region North
ray = rays_n[roo_sq]
blockers = ray & occupancy
if blockers:
blocker_sq = blockers.bit_length() - 1
ray_to_del = rays_n[blocker_sq]
roo_attacks = (ray ^ ray_to_del) & ~friendly_pcs
else:
roo_attacks = ray
while roo_attacks:
to_sq = (roo_attacks & -roo_attacks).bit_length() - 1
to_mask = 1 << to_sq
roo_attacks &= (roo_attacks - 1)
if to_mask & opponent_pcs:
if to_mask & bbs[paw + opp_offset]:
captured = paw + opp_offset
elif to_mask & bbs[nht + opp_offset]:
captured = nht + opp_offset
elif to_mask & bbs[bis + opp_offset]:
captured = bis + opp_offset
elif to_mask & bbs[roo + opp_offset]:
captured = roo + opp_offset
else:
captured = que + opp_offset
captures.append(to_sq | (roo_sq << 6) | ((roo + turn_offset) << 12) | (captured << 16) | capture << 20)
else:
moves.append(to_sq | (roo_sq << 6) | ((roo + turn_offset) << 12) | (no_piece << 16) | quiet << 20)
# endregion
# region East
ray = rays_e[roo_sq]
blockers = ray & occupancy
if blockers:
blocker_sq = blockers.bit_length() - 1
ray_to_del = rays_e[blocker_sq]
roo_attacks = (ray ^ ray_to_del) & ~friendly_pcs
else:
roo_attacks = ray
while roo_attacks:
to_sq = (roo_attacks & -roo_attacks).bit_length() - 1
to_mask = 1 << to_sq
roo_attacks &= (roo_attacks - 1)
if to_mask & opponent_pcs:
if to_mask & bbs[paw + opp_offset]:
captured = paw + opp_offset
elif to_mask & bbs[nht + opp_offset]:
captured = nht + opp_offset
elif to_mask & bbs[bis + opp_offset]:
captured = bis + opp_offset
elif to_mask & bbs[roo + opp_offset]:
captured = roo + opp_offset
else:
captured = que + opp_offset
captures.append(to_sq | (roo_sq << 6) | ((roo + turn_offset) << 12) | (captured << 16) | capture << 20)
else:
moves.append(to_sq | (roo_sq << 6) | ((roo + turn_offset) << 12) | (no_piece << 16) | quiet << 20)
# endregion
# region South
ray = rays_s[roo_sq]
blockers = ray & occupancy
if blockers:
blocker_sq = blockers.bit_length() - 1
ray_to_del = rays_s[blocker_sq]
roo_attacks = (ray ^ ray_to_del) & ~friendly_pcs
else:
roo_attacks = ray
while roo_attacks:
to_sq = (roo_attacks & -roo_attacks).bit_length() - 1
to_mask = 1 << to_sq
roo_attacks &= (roo_attacks - 1)
if to_mask & opponent_pcs:
if to_mask & bbs[paw + opp_offset]:
captured = paw + opp_offset
elif to_mask & bbs[nht + opp_offset]:
captured = nht + opp_offset
elif to_mask & bbs[bis + opp_offset]:
captured = bis + opp_offset
elif to_mask & bbs[roo + opp_offset]:
captured = roo + opp_offset
else:
captured = que + opp_offset
captures.append(to_sq | (roo_sq << 6) | ((roo + turn_offset) << 12) | (captured << 16) | capture << 20)
else:
moves.append(to_sq | (roo_sq << 6) | ((roo + turn_offset) << 12) | (no_piece << 16) | quiet << 20)
# endregion
# region West
ray = rays_w[roo_sq]
blockers = ray & occupancy
if blockers:
blocker_sq = blockers.bit_length() - 1
ray_to_del = rays_w[blocker_sq]
roo_attacks = (ray ^ ray_to_del) & ~friendly_pcs
else:
roo_attacks = ray
while roo_attacks:
to_sq = (roo_attacks & -roo_attacks).bit_length() - 1
to_mask = 1 << to_sq
roo_attacks &= (roo_attacks - 1)
if to_mask & opponent_pcs:
if to_mask & bbs[paw + opp_offset]:
captured = paw + opp_offset
elif to_mask & bbs[nht + opp_offset]:
captured = nht + opp_offset
elif to_mask & bbs[bis + opp_offset]:
captured = bis + opp_offset
elif to_mask & bbs[roo + opp_offset]:
captured = roo + opp_offset
else:
captured = que + opp_offset
captures.append(to_sq | (roo_sq << 6) | ((roo + turn_offset) << 12) | (captured << 16) | capture << 20)
else:
moves.append(to_sq | (roo_sq << 6) | ((roo + turn_offset) << 12) | (no_piece << 16) | quiet << 20)
# endregion
# endregion Rook Moves
return captures, moves
def make_move(self, move):
# Setup
# 6 Bit (0-5): Target (Index: 0-63)
# 6 Bit (6-11): Source (Index: 0-63)
# 4 Bit (12-15): Piece moved (0-11: W_KIN-B_PAW)
# 4 Bit (16-19): Piece Captured (0-11: W_KIN-B_PAW, 15: Nothing)
# Bit 20-23: Flags (4 Bit)
# 0000: 0 Quiet 0100: 4 Capture 1000: 8 Promo NHT
# 0001: 1 Double Pawn Push 0101: 5 En Passant 1001: 9 Promo BIS
# 0010: 2 King Castle 0110: 1010: 10 Promo ROO
# 0011: 3 Queen Castle 0111: 1011: 11 Promo QUE
end = move & 0x3F
start = (move >> 6) & 0x3F
piece = (move >> 12) & 0xF
captured = (move >> 16) & 0xF
flag = (move >> 20) & 0xF
turn = self.side_to_move
self.bitboards[piece] ^= (1 << start) | (1 << end)
self.all_pieces[turn] ^= (1 << start) | (1 << end)
if flag == CAPTURE:
self.bitboards[captured] ^= (1 << end)
self.all_pieces[turn ^ 1] ^= (1 << end)
self.move_list.append(move)
self.side_to_move ^= 1 # Seite Wechseln
def encode_and_make_move(self, move_str: str):
piece = move_str[0]
start = move_str[1:3]
end = move_str[3:5]
piece_int = (PCE_TO_NUM[piece.upper()] + 6) if self.side_to_move else PCE_TO_NUM[piece.upper()]
start_int = STR_TO_SQ[start.upper()]
end_int = STR_TO_SQ[end.upper()]
move_input = end_int | start_int << 6 | piece_int << 12
captures, moves = self.get_all_moves()
for move in captures:
if (move & 0xFFFF) == (move_input & 0xFFFF):
self.make_move(move)
return True
for move in moves:
if (move & 0xFFFF) == (move_input & 0xFFFF):
self.make_move(move)
return True
return False
def print_board(self):
board = [" "] * 64
if self.move_list:
move = self.move_list[-1]
last_sq = (move >> 6) & 0x3F
board[last_sq] = f"{COL.BG_MOVE} "
for pce in range(12):
locations = self.bitboards[pce]
while locations:
index = (locations & -locations).bit_length() - 1
board[index] = PIECE_TO_SYM[pce]
locations &= (locations - 1)
for c in range(7, -1, -1):
print(f"{c+1} ", end="")
for r in range(8):
bg_col = COL.BG_WHITE if (r + c) % 2 != 0 else COL.BG_DARK
#fg_col = COL.FG_WHITE if (board[r + (c * 8)][0]) != "b" else COL.FG_BLACK
print(f"{bg_col}{COL.FG_BLACK}{board[r + (c * 8)]}", end=" ")
print(COL.RESET)
print(" A B C D E F G H\n")
def initialize():
'''
Calculate all Attack patterns and Rays
'''
for sq in range(64):
bit = 1 << sq
# --- Pieces ---
# King
kin_attacks = (bit & NOT_A) << 7 | bit << 8 | (bit & NOT_H) << 9 | (bit & NOT_H) << 1 | \
(bit & NOT_H) >> 7 | bit >> 8 | (bit & NOT_A) >> 9 | (bit & NOT_A) >> 1
KIN_ATTACKS[sq] = kin_attacks & FULL_MASK
# Knight
nht_attacks = (bit & NOT_AB) << 6 | (bit & NOT_A) << 15 | (bit & NOT_H) << 17 | (bit & NOT_GH) << 10 | \
(bit & NOT_GH) >> 6 | (bit & NOT_H) >> 15 | (bit & NOT_A) >> 17 | (bit & NOT_AB) >> 10
NHT_ATTACKS[sq] = nht_attacks & FULL_MASK
# Pawns Attack
w_attacks = (bit & NOT_A) << 7 | (bit & NOT_H) << 9
PAW_ATTACKS[sq] = w_attacks & FULL_MASK
b_attacks = (bit & NOT_A) >> 9 | (bit & NOT_H) >> 7
PAW_ATTACKS[sq + 64] = b_attacks & FULL_MASK
# --- Rays ---
r, f = sq // 8, sq % 8
# North (r+)
RAYS_N[sq] = 0
for i in range(r + 1, 8):
RAYS_N[sq] |= (1 << (i * 8 + f))
# South (r-)
RAYS_S[sq] = 0
for i in range(r - 1, -1, -1):
RAYS_S[sq] |= (1 << (i * 8 + f))
# East (f+)
RAYS_E[sq] = 0
for i in range(f + 1, 8):
RAYS_E[sq] |= (1 << (r * 8 + i))
# West (f-)
RAYS_W[sq] = 0
for i in range(f - 1, -1, -1):
RAYS_W[sq] |= (1 << (r * 8 + i))
# North-East (r+, f+)
RAYS_NE[sq] = 0
i, j = r + 1, f + 1
while i < 8 and j < 8:
RAYS_NE[sq] |= (1 << (i * 8 + j))
i += 1; j += 1
# North-West (r+, f-)
RAYS_NW[sq] = 0
i, j = r + 1, f - 1
while i < 8 and j >= 0:
RAYS_NW[sq] |= (1 << (i * 8 + j))
i += 1; j -= 1
# South-East (r-, f+)
RAYS_SE[sq] = 0
i, j = r - 1, f + 1
while i >= 0 and j < 8:
RAYS_SE[sq] |= (1 << (i * 8 + j))
i -= 1; j += 1
# South-West (r-, f-)
RAYS_SW[sq] = 0
i, j = r - 1, f - 1
while i >= 0 and j >= 0:
RAYS_SW[sq] |= (1 << (i * 8 + j))
i -= 1; j -= 1
initialize()
board = Bitboard()
turn = 0
text = f"Please input move: "
while board.playing:
clear()
print(f"{COL.RESET}\n ---- CHESS ---- Turn: {turn}")
board.print_board()
move = input(text)
if move == "exit":
break
if len(move) !=5 or not board.encode_and_make_move(move):
text = "Move not possible new move: "
continue
turn += 1
PIECE_TO_UNICODE = {"wk": "\u2654 ", "wq": "\u2655 ", "wr": "\u2656 ", "wb": "\u2657 ", "wn": "\u2658 ", "wp": "\u2659 ",
"bk": "\u265A ", "bq": "\u265B ", "br": "\u265C ", "bb": "\u265D ", "bn": "\u265E ", "bp": "\u265F "}
INDEX_TO_FIELD = [
"a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1",
"a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2",
"a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3",
"a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4",
"a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5",
"a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6",
"a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7",
"a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8",
]
''' Board Index: ''' Board Index:
a b c d e f g h a b c d e f g h
@@ -26,126 +706,3 @@ INDEX_TO_FIELD = [
1 [00] [01] [02] [03] [03] [05] [06] [07] 1 [00] [01] [02] [03] [03] [05] [06] [07]
''' '''
class Piece():
def __init__(self, pce_type, is_white, index):
self.type = pce_type
self.is_white = is_white
self.has_castled = False if type == 'K' else True
self.index = index
self.bit_mask = 1 << index
class Move():
def __init__(self, start_index, end_index, piece_moved, piece_captured=None):
self.piece_moved = piece_moved
self.piece_captured = piece_captured
self.index_start = start_index
self.index_end = end_index
self.bitmask_start: int = 1 << start_index
self.bitmask_end = 1 << end_index
self.chess_notation = f"{self.piece_moved[1].upper()}{INDEX_TO_FIELD[self.index_start]}{INDEX_TO_FIELD[self.index_end]}"
class Board():
def __init__(self):
self.bit_mask_w = 0x0000000000000001FE7F800
self.bit_mask_b = 0x1FE7F800000000000000000
self.bit_mask_all=0x1FE7F80000000001FE7F800
self.white_to_move = True
# self.wr1 = Piece('R', True, 11)
# self.wn1 = Piece('N', True, 12)
# self.wb1 = Piece('B', True, 13)
# self.wk = Piece('K', True, 14)
# self.wq = Piece('Q', True, 15)
# self.wb2 = Piece('B', True, 16)
# self.wn2 = Piece('N', True, 17)
# self.wr2 = Piece('R', True, 18)
# self.wp = [Piece('P', True, 21),
# Piece('P', True, 22),
# Piece('P', True, 23),
# Piece('P', True, 24),
# Piece('P', True, 25),
# Piece('P', True, 26),
# Piece('P', True, 27),
# Piece('P', True, 28)]
self.piece_dict = {
'br1':81, 'bn1':82, 'bb1':83, 'bk' :84, 'bq' :85, 'bb2':86, 'bn2':87, 'br2':88,
'bp1':71, 'bp2':72, 'bp3':73, 'bp4':74, 'bp5':75, 'bp6':76, 'bp7':77, 'bp8':78,
'wp1':21, 'wp2':22, 'wp3':23, 'wp4':24, 'wp5':25, 'wp6':26, 'wp7':27, 'wp8':28,
'wr1':11, 'wn1':12, 'wb1':13, 'wk' :14, 'wq' :15, 'wb2':16, 'wn2':17, 'wr2':18,
}
self.move_log = []
def print_board(self):
for x in range(100):
if OUT_OF_BOARD & 1 << x != 0:
if (x+1) % 10 == 0:
print("")
continue
continue
if self.bit_mask_all & 1 << x != 0:
for p in self.piece_dict:
if self.piece_dict[p] == x:
print(f"{PIECE_TO_UNICODE[p[:2]]} ", end="")
else:
print("\u25FB ", end="")
def notation_to_move(self, notation_str): # Kb1a5
if len(notation_str) < 6:
start = INDEX_TO_FIELD.index(notation_str[1]+ notation_str[2])
end = INDEX_TO_FIELD.index(notation_str[3]+ notation_str[4])
for p in self.piece_dict:
if self.piece_dict[p] == start:
piece_moved = p
if self.piece_dict[p] == end:
piece_captured = p
if piece_moved and piece_captured:
return Move(start, end, piece_moved, piece_captured)
elif piece_moved:
return Move(start, end, piece_moved)
else:
print("No Piece to Move")
return
else:
print("Move to long")
return
def make_move(self, move):
self.piece_dict[move.piece_moved] = move.index_start
if self.white_to_move:
self.bit_mask_w = self.bit_mask_w & ~move.bitmask_start
self.bit_mask_w = self.bit_mask_w | move.bitmask_end
if move.piece_captured:
self.piece_dict[move.piece_captured] = -1
self.bit_mask_b = self.bit_mask_b & ~move.bitmask_end
else:
self.bit_mask_b = self.bit_mask_b & ~move.bitmask_start
self.bit_mask_b = self.bit_mask_b | move.bitmask_end
if move.piece_captured:
self.piece_dict[move.piece_captured] = -1
self.bit_mask_b = self.bit_mask_b & ~move.bitmask_end
self.bit_mask_all = self.bit_mask_w | self.bit_mask_b
self.move_log.append(move)
board = Board()
board.print_board()
while True:
print("Your Move, Please: ")
move_str = input()
if len(move_str) != 4:
print("Wrong Syntax")
continue
move = board.notation_to_move(move_str)
board.make_move(move)

358
games/barcafinal.html Normal file
View File

@@ -0,0 +1,358 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Barça History Master: Final 120 Facts Edition</title>
<style>
:root {
--barca-blue: #004d98;
--barca-red: #a50044;
--barca-gold: #edbb00;
--white: #ffffff;
--dark-blue: #002d5a;
--glass: rgba(255, 255, 255, 0.1);
}
* { box-sizing: border-box; transition: all 0.3s ease; }
body, html {
height: 100%; margin: 0; font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
background: radial-gradient(circle, var(--barca-blue), var(--dark-blue));
color: var(--white); display: flex; justify-content: center; align-items: center; overflow: hidden;
}
.bg-pattern {
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
background-image: linear-gradient(45deg, var(--barca-blue) 25%, transparent 25%),
linear-gradient(-45deg, var(--barca-blue) 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, var(--barca-blue) 75%),
linear-gradient(-45deg, transparent 75%, var(--barca-blue) 75%);
background-size: 100px 100px; opacity: 0.1; z-index: -1;
}
#menu-screen { width: 90%; max-width: 1100px; text-align: center; }
h1 { font-size: clamp(2.5rem, 6vw, 4.5rem); font-weight: 900; letter-spacing: -2px; text-shadow: 0 10px 20px rgba(0,0,0,0.5); margin-bottom: 40px; }
h1 span { color: var(--barca-gold); }
.category-grid {
display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 25px;
}
.cat-card {
background: var(--glass); backdrop-filter: blur(15px);
border: 2px solid rgba(255,255,255,0.1); border-radius: 30px;
padding: 40px 20px; cursor: pointer; border-bottom: 6px solid var(--barca-gold);
}
.cat-card:hover { transform: translateY(-15px); background: rgba(255,255,255,0.2); border-color: var(--white); box-shadow: 0 20px 40px rgba(0,0,0,0.4); }
.cat-card h2 { font-size: 1.8rem; margin: 15px 0; color: var(--barca-gold); }
#quiz-card {
display: none; width: 95%; max-width: 900px; height: 85vh;
background: rgba(255, 255, 255, 0.98); color: #1a1a1a; border-radius: 40px;
box-shadow: 0 50px 100px rgba(0,0,0,0.6); overflow: hidden;
flex-direction: column; border: 4px solid var(--barca-gold);
}
.quiz-header {
background: linear-gradient(to right, var(--barca-blue), var(--barca-red));
color: #fff; padding: 25px 40px; display: flex; justify-content: space-between; align-items: center;
}
.difficulty-container {
padding: 15px 0; display: flex; justify-content: center; align-items: center;
}
.difficulty-badge {
font-size: 1.2rem; font-weight: 800; padding: 8px 25px; border-radius: 50px;
text-transform: uppercase; letter-spacing: 1px; box-shadow: 0 4px 10px rgba(0,0,0,0.1);
}
.diff-leicht { background: #e8f5e9; color: #2e7d32; border: 2px solid #2e7d32; }
.diff-mittel { background: #fff3e0; color: #ef6c00; border: 2px solid #ef6c00; }
.diff-schwer { background: #ffebee; color: #c62828; border: 2px solid #c62828; }
.quiz-content { padding: 40px; flex-grow: 1; text-align: center; }
.question { font-size: 1.8rem; font-weight: 800; color: var(--dark-blue); margin-bottom: 35px; min-height: 80px; }
.options-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
button.opt {
padding: 20px; font-size: 1.1rem; font-weight: 700; background: #f5f7fa;
border: 2px solid #e1e8ed; border-radius: 20px; cursor: pointer; color: #333;
}
button.opt:hover { background: var(--barca-blue); color: white; transform: scale(1.03); }
.correct { background: #2ecc71 !important; color: white !important; }
.wrong { background: #e74c3c !important; color: white !important; }
#slot-screen { display: none; padding: 40px; text-align: center; overflow-y: auto; height: 100%; }
.slot-box {
background: #1a1a1a; padding: 30px; border-radius: 30px; margin: 20px auto;
border: 4px solid var(--barca-gold); max-width: 500px;
}
#slot-val { font-size: 2.2rem; color: var(--barca-gold); font-weight: 900; text-shadow: 0 0 15px var(--barca-gold); height: 50px; }
.rank-table {
width: 100%; max-width: 500px; margin: 30px auto; border-radius: 20px; overflow: hidden;
border-collapse: collapse; background: #fff; box-shadow: 0 10px 30px rgba(0,0,0,0.1);
}
.rank-table th { background: var(--barca-blue); color: white; padding: 15px; }
.rank-table td { padding: 15px; border-bottom: 1px solid #eee; color: #333; font-weight: 600; }
.rank-active { background: var(--barca-gold) !important; color: #000 !important; transform: scale(1.05); }
.btn-restart {
margin-top: 20px; padding: 15px 40px; background: var(--barca-red); color: white;
border: none; border-radius: 50px; font-weight: 900; cursor: pointer; text-transform: uppercase;
}
</style>
</head>
<body>
<div class="bg-pattern"></div>
<div id="menu-screen">
<h1><span>MÉS QUE UN</span> QUIZ</h1>
<div class="category-grid">
<div class="cat-card" onclick="startQuiz('90')">
<h2>1990 - 2000</h2>
<p>Das Dream Team & Wembley '92</p>
</div>
<div class="cat-card" onclick="startQuiz('00')">
<h2>2000 - 2010</h2>
<p>Ronaldinho & Pep-Revolution</p>
</div>
<div class="cat-card" onclick="startQuiz('10')">
<h2>2010 - HEUTE</h2>
<p>MSN & Die goldene Ära</p>
</div>
</div>
</div>
<div id="quiz-card">
<div id="quiz-main" style="display: flex; flex-direction: column; height: 100%;">
<div class="quiz-header">
<span id="era-label" style="font-weight: 900; font-size: 1.2rem;">KATEGORIE</span>
<span id="progress" style="font-weight: 900; font-size: 1.4rem;">1 / 20</span>
</div>
<div class="difficulty-container">
<div id="diff-tag" class="difficulty-badge">Mittel</div>
</div>
<div class="quiz-content">
<div class="question" id="q-text">Lade Frage...</div>
<div class="options-grid" id="opt-container"></div>
</div>
</div>
<div id="slot-screen">
<h1 style="color: #1a1a1a; font-size: 2.5rem; margin-bottom: 10px;">DEIN RESULTAT</h1>
<div class="slot-box">
<div id="slot-val">???</div>
<button class="btn-restart" id="lever" onclick="runSlot()" style="background: var(--barca-blue); margin-top: 25px;">Zieh den Hebel</button>
</div>
<table class="rank-table">
<thead><tr><th>Rang</th><th>Korrekte Antworten</th></tr></thead>
<tbody>
<tr id="r-4"><td>THE GOAT 🐐</td><td>19 - 20</td></tr>
<tr id="r-3"><td>BARÇA LEGENDE 🏆</td><td>16 - 18</td></tr>
<tr id="r-2"><td>STAMMSPIELER ⚽</td><td>12 - 15</td></tr>
<tr id="r-1"><td>TREUER FAN 🏟️</td><td>6 - 11</td></tr>
<tr id="r-0"><td>PLASTIKFAN 🤡</td><td>0 - 5</td></tr>
</tbody>
</table>
<p style="color: #333; font-weight: 900; font-size: 1.5rem;">SCORE: <span id="final-score" style="color: var(--barca-red);">0</span> / 20</p>
<button onclick="location.reload()" class="btn-restart">Hauptmenü</button>
</div>
</div>
<script>
const questions = {
'90': [
{q:"Wer erzielte das Freistoßtor im CL-Finale 1992 gegen Sampdoria?", a:["Ronald Koeman","Hristo Stoichkov","José Mari Bakero","Michael Laudrup"], c:0, d:"Leicht"},
{q:"Wie viele La-Liga-Titel gewann das Dream Team unter Johan Cruyff in Folge?", a:["Zwei","Drei","Vier","Fünf"], c:2, d:"Mittel"},
{q:"Welcher brasilianische Stürmer kam 1993 vom PSV Eindhoven?", a:["Ronaldo","Romário","Rivaldo","Sonny Anderson"], c:1, d:"Leicht"},
{q:"Wer löste Johan Cruyff im Jahr 1996 als Trainer ab?", a:["Louis van Gaal","Bobby Robson","Radomir Antić","Terry Venables"], c:1, d:"Mittel"},
{q:"Welchen Spitznamen hatte Hristo Stoichkov aufgrund seines Temperaments?", a:["El Mago","El Pistolero","El Búlgaro","Der Dolch"], c:2, d:"Leicht"},
{q:"Gegen wen verlor Barca das bittere CL-Finale 1994 mit 0:4?", a:["Juventus Turin","AC Mailand","Ajax Amsterdam","Real Madrid"], c:1, d:"Mittel"},
{q:"In welchem Jahr feierte der FC Barcelona sein 100-jähriges Bestehen?", a:["1998","1999","2000","1997"], c:1, d:"Leicht"},
{q:"Welche Nummer trug Pep Guardiola primär im Dream Team?", a:["Nr. 4","Nr. 6","Nr. 8","Nr. 10"], c:0, d:"Mittel"},
{q:"Welcher Star wechselte im Jahr 2000 für eine Rekordsumme zu Real Madrid?", a:["Rivaldo","Luís Figo","Luis Enrique","Patrick Kluivert"], c:1, d:"Leicht"},
{q:"Wer erzielte 1996/97 unglaubliche 47 Tore in einer einzigen Saison?", a:["Ronaldo (R9)","Romário","Rivaldo","Luis Enrique"], c:0, d:"Leicht"},
{q:"Wer war der Kapitän beim ersten CL-Sieg der Vereinsgeschichte 1992?", a:["Andoni Zubizarreta","José Ramón Alexanko","José Mari Bakero","Pep Guardiola"], c:1, d:"Schwer"},
{q:"Aus welchem Land kam der Spielmacher Michael Laudrup?", a:["Schweden","Dänemark","Norwegen","Niederlande"], c:1, d:"Leicht"},
{q:"Wer erzielte den entscheidenden Hattrick beim 5:0 im Clásico 1994?", a:["Romário","Stoichkov","Iván Iglesias","Bakero"], c:0, d:"Schwer"},
{q:"Welcher niederländische Trainer kam 1997 und brachte viele Ajax-Stars mit?", a:["Frank Rijkaard","Louis van Gaal","Dick Advocaat","Guus Hiddink"], c:1, d:"Leicht"},
{q:"Wer war der Stammtorhüter von 1986 bis 1994?", a:["Vítor Baía","Andoni Zubizarreta","Carles Busquets","Ruud Hesp"], c:1, d:"Mittel"},
{q:"Gegen wen gewann Barca das Finale der Pokalsieger 1997?", a:["Paris Saint-Germain","FC Liverpool","FC Arsenal","FC Porto"], c:0, d:"Schwer"},
{q:"Welcher Star kam 1997 als direkter Ersatz für Ronaldo von La Coruña?", a:["Rivaldo","Djalminha","Flávio Conceição","Bebeto"], c:0, d:"Mittel"},
{q:"Welche Nationalität hat Gheorghe Popescu (Kapitän 1996/97)?", a:["Bulgarisch","Rumänisch","Ungarisch","Kroatisch"], c:1, d:"Schwer"},
{q:"In welchem Londoner Stadion gewann Barca 1992 den Europapokal?", a:["Highbury","Wembley","Stamford Bridge","White Hart Lane"], c:1, d:"Leicht"},
{q:"Wie viele Tore schoss Romário in der La Liga Saison 93/94?", a:["26","30","34","38"], c:1, d:"Schwer"},
{q:"Wer war der Vizepräsident und Nachfolger von Josep Lluís Núñez im Jahr 2000?", a:["Joan Laporta","Joan Gaspart","Sandro Rosell","Enric Reyna"], c:1, d:"Schwer"},
{q:"Welcher Verteidiger trug den Spitznamen 'Tarzan'?", a:["Migueli","Albert Ferrer","Sergi Barjuán","Nadal"], c:0, d:"Schwer"},
{q:"Wer war der Übersetzer und Co-Trainer von Bobby Robson?", a:["Pep Guardiola","José Mourinho","Luis Enrique","Tito Vilanova"], c:1, d:"Mittel"},
{q:"Welcher niederländische Flügelstürmer kam 2000 für eine hohe Ablöse von Arsenal?", a:["Marc Overmars","Patrick Kluivert","Boudewijn Zenden","Philip Cocu"], c:0, d:"Mittel"},
{q:"Welcher Torwart hielt 1997-2000 den Kasten sauber?", a:["Ruud Hesp","Pepe Reina","Vítor Baía","Francesc Arnau"], c:0, d:"Schwer"},
{q:"Wer schoss das Goldene Tor im Finale der Pokalsieger 1997 per Elfmeter?", a:["Luís Figo","Ronaldo","Luis Enrique","Ivan de la Peña"], c:1, d:"Mittel"},
{q:"Welcher Star wechselte 1996 von Real Madrid direkt zum FC Barcelona?", a:["Luis Enrique","Michael Laudrup","Luís Figo","Gheorghe Hagi"], c:0, d:"Leicht"},
{q:"Wer erzielte das Tor des Jahrhunderts gegen Compostela 1996?", a:["Rivaldo","Ronaldo","Ronaldinho","Romário"], c:1, d:"Mittel"},
{q:"Aus welchem Land kam der Verteidiger Patrik Andersson (Ende der 90er)?", a:["Dänemark","Schweden","Norwegen","Finnland"], c:1, d:"Schwer"},
{q:"Gegen wen sicherte sich Barca 1999 am 100. Geburtstag die Meisterschaft?", a:["Real Madrid","Deportivo La Coruña","Deportivo Alavés","Atletico Madrid"], c:2, d:"Schwer"},
{q:"Welcher spätere Welttrainer spielte im Mittelfeld neben Guardiola?", a:["Luis Enrique","Luis Milla","Eusebio Sacristán","Guillermo Amor"], c:0, d:"Mittel"},
{q:"Was war die Besonderheit am CL-Trikot 1992?", a:["Es war Orange","Es hatte Kragen","Es war Weiß","Es hatte keine Streifen"], c:0, d:"Leicht"},
{q:"Wer war der Star-Einkauf aus Finnland im Jahr 1999?", a:["Jari Litmanen","Sami Hyypiä","Mikael Forssell","Teemu Pukki"], c:0, d:"Mittel"},
{q:"Welcher Außenverteidiger trug die Nummer 2 im Dream Team?", a:["Albert Ferrer","Sergi Barjuán","Nando","Juan Carlos"], c:0, d:"Schwer"},
{q:"Wie oft wurde Barca in den 90ern spanischer Meister?", a:["4 Mal","5 Mal","6 Mal","7 Mal"], c:2, d:"Schwer"},
{q:"Wer schoss 1992 im Halbfinale gegen Benfica das wichtige 1:0?", a:["Bakero","Stoichkov","Laudrup","Begiristain"], c:1, d:"Schwer"},
{q:"Welche Marke löste Kappa 1998 als Ausrüster ab?", a:["Adidas","Nike","Puma","Meyba"], c:1, d:"Leicht"},
{q:"Welcher Verteidiger war der Onkel von Tennis-Star Rafael Nadal?", a:["Miguel Ángel Nadal","Abelardo","Sergi","Nando"], c:0, d:"Mittel"},
{q:"Wer erzielte den entscheidenden Treffer im Finale der Copa del Rey 1997 (3:2 gegen Betis)?", a:["Pizzi","Figo","Luis Enrique","Ronaldo"], c:1, d:"Schwer"},
{q:"Welcher Star verließ Barca 1994 Richtung Real Madrid?", a:["Michael Laudrup","Robert Prosinečki","Luis Milla","Gheorghe Hagi"], c:0, d:"Mittel"}
],
'00': [
{q:"Wer kam 2003 für ca. 30 Mio. Euro von Paris Saint-Germain?", a:["David Beckham","Ronaldinho","Ricardo Quaresma","Samuel Eto'o"], c:1, d:"Leicht"},
{q:"Gegen wen gewann Barca das Champions-League-Finale 2006?", a:["Manchester United","Arsenal London","FC Chelsea","AC Mailand"], c:1, d:"Leicht"},
{q:"Wer schoss das 2:1 Siegtor im CL-Finale 2006?", a:["Samuel Eto'o","Juliano Belletti","Henrik Larsson","Ludovic Giuly"], c:1, d:"Mittel"},
{q:"In welchem Jahr gewann der FC Barcelona das erste 'Sextuple'?", a:["2008","2009","2010","2011"], c:1, d:"Leicht"},
{q:"Welcher Trainer startete 2008 die Ära des Tiki-Taka?", a:["Frank Rijkaard","Pep Guardiola","Luis Enrique","Tito Vilanova"], c:1, d:"Leicht"},
{q:"Welche Rückennummer trug Lionel Messi bei seinem Profi-Debüt?", a:["Nr. 10","Nr. 19","Nr. 30","Nr. 14"], c:2, d:"Mittel"},
{q:"Wer erzielte im CL-Halbfinale 2009 das 'Iniestazo'-Tor an der Stamford Bridge?", a:["Lionel Messi","Andrés Iniesta","Xavi","Samuel Eto'o"], c:1, d:"Leicht"},
{q:"Gegen wen erzielte Messi 2007 sein legendäres Solo-Tor (wie Maradona)?", a:["Real Madrid","Getafe CF","RCD Espanyol","FC Valencia"], c:1, d:"Mittel"},
{q:"Wer war der Kapitän während der gesamten Ära Guardiola?", a:["Xavi","Carles Puyol","Andrés Iniesta","Víctor Valdés"], c:1, d:"Leicht"},
{q:"Welcher Stürmer kam 2004 von RCD Mallorca?", a:["Henrik Larsson","Samuel Eto'o","Maxi López","Santi Ezquerro"], c:1, d:"Leicht"},
{q:"Aus welchem Club kam Deco im Jahr 2004?", a:["FC Porto","Benfica Lissabon","Sporting Lissabon","Real Madrid"], c:0, d:"Mittel"},
{q:"Wer schoss das erste Tor im CL-Finale 2009 gegen Manchester United?", a:["Lionel Messi","Samuel Eto'o","Thierry Henry","Andrés Iniesta"], c:1, d:"Mittel"},
{q:"Welcher Sponsor stand ab 2006 erstmals auf dem Trikot (für den guten Zweck)?", a:["Qatar Airways","UNICEF","Rakuten","Beko"], c:1, d:"Leicht"},
{q:"Wer kam 2008 vom FC Sevilla als Rechtsverteidiger?", a:["Dani Alves","Adriano","Maxwell","Belletti"], c:0, d:"Leicht"},
{q:"Wer war der Torwart beim Champions-League-Sieg 2006?", a:["Rustu Reçber","Víctor Valdés","José Manuel Pinto","Pepe Reina"], c:1, d:"Mittel"},
{q:"Wer wechselte 2009 im Tausch für Samuel Eto'o nach Barcelona?", a:["David Villa","Zlatan Ibrahimović","Thierry Henry","Diego Forlán"], c:1, d:"Leicht"},
{q:"Aus welchem Land kommt der Verteidiger Rafael Márquez?", a:["Brasilien","Mexiko","Argentinien","Kolumbien"], c:1, d:"Leicht"},
{q:"Welcher Isländer spielte von 2006 bis 2009 bei Barca?", a:["Eidur Gudjohnsen","Gylfi Sigurdsson","Aron Gunnarsson","Alfreð Finnbogason"], c:0, d:"Mittel"},
{q:"Wer bereitete im Finale 2006 beide Tore nach seiner Einwechslung vor?", a:["Andrés Iniesta","Henrik Larsson","Mark van Bommel","Xavi"], c:1, d:"Schwer"},
{q:"Wer war der Präsident von 2003 bis 2010?", a:["Sandro Rosell","Joan Laporta","Joan Gaspart","Josep Maria Bartomeu"], c:1, d:"Leicht"},
{q:"Gegen wen feierte Barca 2009 den historischen 6:2 Auswärtssieg?", a:["Atletico Madrid","Real Madrid","Espanyol Barcelona","FC Sevilla"], c:1, d:"Leicht"},
{q:"Welcher Mittelfeldspieler kam 2005 vom PSV Eindhoven?", a:["Mark van Bommel","Ibrahim Afellay","Philip Cocu","Park Ji-sung"], c:0, d:"Schwer"},
{q:"In welchem Stadion gewann Barca das CL-Finale 2006?", a:["Wembley","Stade de France","San Siro","Olympiastadion Berlin"], c:1, d:"Mittel"},
{q:"Wer erzielte im Clásico 2005 im Bernabéu zwei Tore und bekam Standing Ovations?", a:["Lionel Messi","Ronaldinho","Samuel Eto'o","Xavi"], c:1, d:"Mittel"},
{q:"Welche Nummer trug Thierry Henry bei Barca?", a:["Nr. 9","Nr. 14","Nr. 7","Nr. 12"], c:1, d:"Leicht"},
{q:"Welcher Argentinier kam 2001 für eine Rekordsumme von River Plate?", a:["Juan Román Riquelme","Javier Saviola","Pablo Aimar","Gabriel Milito"], c:1, d:"Schwer"},
{q:"Wer war Trainer vor Frank Rijkaard (Saison 2002/03)?", a:["Louis van Gaal","Radomir Antić","Carles Rexach","Llorenç Serra Ferrer"], c:1, d:"Schwer"},
{q:"Wer schoss den Kopfballtreffer zum 2:0 im Finale 2009?", a:["Samuel Eto'o","Gerard Piqué","Lionel Messi","Carles Puyol"], c:2, d:"Mittel"},
{q:"Welcher Brasilianer kam 2001 von Cruzeiro und galt als Flop?", a:["Geovanni","Fabio Rochemback","Douglas","Keirrison"], c:1, d:"Schwer"},
{q:"Wie oft wurde Ronaldinho während seiner Zeit bei Barca Weltfußballer?", a:["1 Mal","2 Mal","3 Mal","Kein Mal"], c:1, d:"Mittel"},
{q:"Wer war 2003 der Trainer-Favorit von Gegenkandidat Lluis Bassat?", a:["Frank Rijkaard","Ronald Koeman","Pep Guardiola","Guus Hiddink"], c:1, d:"Schwer"},
{q:"Welcher Franzose trug die Nummer 8 vor Andrés Iniesta?", a:["Ludovic Giuly","Christophe Dugarry","Philippe Christanval","Emmanuel Petit"], c:0, d:"Schwer"},
{q:"Aus welchem Verein kam Gerard Piqué 2008 zurück nach Hause?", a:["Manchester United","Arsenal London","Real Saragossa","FC Liverpool"], c:0, d:"Leicht"},
{q:"Wer erzielte 2005 das erste offizielle Tor für Messi (Vorlage Ronaldinho)?", a:["Albacete","Getafe","Sevilla","Malaga"], c:0, d:"Schwer"},
{q:"Welcher Nationalität ist Edgar Davids (Leihe 2004)?", a:["Suriname","Niederlande","Belgien","Frankreich"], c:1, d:"Mittel"},
{q:"Wie hieß der Co-Trainer von Frank Rijkaard?", a:["Henk ten Cate","Tito Vilanova","Juan Carlos Unzué","Eusebio"], c:0, d:"Schwer"},
{q:"Welcher Star kam 2006 vom Absteiger Juventus Turin?", a:["Lilian Thuram","Zlatan Ibrahimovic","Fabio Cannavaro","David Trezeguet"], c:0, d:"Mittel"},
{q:"Wer schoss das entscheidende Tor zur Meisterschaft 2005 gegen Levante?", a:["Samuel Eto'o","Ronaldinho","Ludovic Giuly","Xavi"], c:0, d:"Schwer"},
{q:"Welcher Mittelfeldspieler trug die Nummer 20 unter Rijkaard?", a:["Deco","Edmilson","Motta","Van Bommel"], c:0, d:"Mittel"},
{q:"Wer war der Stammtorwart in der Katastrophensaison 2002/03?", a:["Roberto Bonano","Víctor Valdés","Robert Enke","Pepe Reina"], c:0, d:"Schwer"}
],
'10': [
{q:"Wer bildete das legendäre 'MSN'-Angriffstrio?", a:["Messi, Suarez, Neymar","Messi, Suarez, Pedro","Messi, Villa, Sanchez","Messi, Neymar, Griezmann"], c:0, d:"Leicht"},
{q:"Wer war der Trainer beim zweiten Triple-Gewinn im Jahr 2015?", a:["Pep Guardiola","Luis Enrique","Tito Vilanova","Gerardo Martino"], c:1, d:"Leicht"},
{q:"Gegen welchen Club gelang die historische 'Remontada' (6:1) im Jahr 2017?", a:["Bayern München","Paris Saint-Germain","Manchester City","Juventus Turin"], c:1, d:"Leicht"},
{q:"Wie viele Tore erzielte Lionel Messi im Kalenderjahr 2012 (Weltrekord)?", a:["85 Tore","91 Tore","73 Tore","95 Tore"], c:1, d:"Leicht"},
{q:"Wer kam 2014 vom FC Liverpool als neuer Top-Stürmer?", a:["Philippe Coutinho","Luis Suárez","Raheem Sterling","Sadio Mané"], c:1, d:"Leicht"},
{q:"Gegen wen gewann Barcelona das CL-Finale 2015 in Berlin?", a:["Juventus Turin","Real Madrid","FC Bayern","Manchester United"], c:0, d:"Mittel"},
{q:"Wer erzielte das Tor zum 1:0 im CL-Finale 2015?", a:["Luis Suárez","Ivan Rakitić","Neymar","Lionel Messi"], c:1, d:"Mittel"},
{q:"Welcher deutsche Torhüter wurde 2014 als Nachfolger von Valdés verpflichtet?", a:["Marc-André ter Stegen","Bernd Leno","Manuel Neuer","Kevin Trapp"], c:0, d:"Leicht"},
{q:"Wer trug die Nummer 10 direkt nach Lionel Messis Abgang 2021?", a:["Pedri","Ansu Fati","Gavi","Ferran Torres"], c:1, d:"Mittel"},
{q:"In welchem Jahr verließ Lionel Messi den Verein Richtung Paris?", a:["2020","2021","2022","2019"], c:1, d:"Leicht"},
{q:"Wer war der Trainer beim 2:8-Debakel gegen Bayern München?", a:["Ernesto Valverde","Quique Setién","Ronald Koeman","Xavi"], c:1, d:"Mittel"},
{q:"Wer schoss im CL-Finale 2011 das Tor zum 2:1 gegen ManUnited?", a:["Pedro","Lionel Messi","David Villa","Xavi"], c:1, d:"Mittel"},
{q:"Welcher kroatische Mittelfeldspieler kam 2014 vom FC Sevilla?", a:["Luka Modrić","Ivan Rakitić","Mateo Kovačić","Ivan Perišić"], c:1, d:"Leicht"},
{q:"Wie hieß der Trainer der Saison 2012/13, der leider 2014 verstarb?", a:["Tata Martino","Tito Vilanova","Luis Enrique","Ernesto Valverde"], c:1, d:"Mittel"},
{q:"Aus welchem Club wechselte Neymar im Jahr 2013 nach Barcelona?", a:["FC Santos","Flamengo","FC São Paulo","Palmeiras"], c:0, d:"Leicht"},
{q:"Wer war der Kapitän der Mannschaft beim Champions-League-Sieg 2011?", a:["Carles Puyol","Xavi","Lionel Messi","Éric Abidal"], c:1, d:"Schwer"},
{q:"Welcher Franzose wechselte 2017 von Dortmund nach Barcelona?", a:["Antoine Griezmann","Ousmane Dembélé","Clément Lenglet","Samuel Umtiti"], c:1, d:"Leicht"},
{q:"In welchem Ausweichstadion spielt Barca während der Camp-Nou-Renovierung 2023/24?", a:["Montjuïc (Lluís Companys)","Mini Estadi","Cornellà-El Prat","RCDE Stadium"], c:0, d:"Mittel"},
{q:"Wer erzielte im Jahr 2023 das entscheidende Tor zur Meisterschaft gegen Espanyol?", a:["Robert Lewandowski","Alejandro Balde","Ferran Torres","Jules Koundé"], c:0, d:"Schwer"},
{q:"Welcher defensive Mittelfeldspieler kam 2010 von Liverpool (Spitzname 'El Jefecito')?", a:["Javier Mascherano","Xabi Alonso","Lucas Leiva","Fabinho"], c:0, d:"Mittel"},
{q:"Wie viele Titel gewann Barca in der Debüt-Saison von Luis Enrique?", a:["Zwei","Drei (Triple)","Vier","Sextuple"], c:1, d:"Leicht"},
{q:"Gegen wen schoss Sergi Roberto das entscheidende 6:1 Tor?", a:["Kevin Trapp","Salvatore Sirigu","Alphonse Areola","Gianluigi Buffon"], c:0, d:"Schwer"},
{q:"Wer kam 2022 ablösefrei vom FC Chelsea für die Abwehr?", a:["Andreas Christensen","Antonio Rüdiger","César Azpilicueta","Marcos Alonso"], c:0, d:"Mittel"},
{q:"Welche Nummer trug Xavi in seiner letzten Saison 2014/15?", a:["Nr. 6","Nr. 8","Nr. 4","Nr. 22"], c:0, d:"Leicht"},
{q:"Aus welchem Land stammt der Mittelfeldspieler Frenkie de Jong?", a:["Belgien","Niederlande","Dänemark","Deutschland"], c:1, d:"Leicht"},
{q:"Wer war der Trainer beim Gewinn der Meisterschaft 2022/23?", a:["Ronald Koeman","Xavi Hernández","Quique Setién","Ernesto Valverde"], c:1, d:"Leicht"},
{q:"Welchen Rekord brach Lamine Yamal 2023 bei seinem Debüt?", a:["Jüngster Torschütze","Jüngster Spieler der Geschichte","Schnellster Sprint","Meiste Vorlagen"], c:1, d:"Mittel"},
{q:"Wer schoss im Finale 2011 das herrliche Schlenzer-Tor zum 3:1?", a:["David Villa","Lionel Messi","Pedro","Dani Alves"], c:0, d:"Mittel"},
{q:"Welcher Sponsor löste 2022 Rakuten auf dem Trikot ab?", a:["Spotify","Apple","Google","Amazon"], c:0, d:"Leicht"},
{q:"Wer war der Rekordtransfer des Sommers 2019 (120 Mio.)?", a:["Philippe Coutinho","Antoine Griezmann","João Félix","Frenkie de Jong"], c:1, d:"Mittel"},
{q:"Aus welchem Land stammt Ronald Araújo?", a:["Brasilien","Uruguay","Argentinien","Chile"], c:1, d:"Mittel"},
{q:"Welcher Torwart hielt im Clásico 2017 (3:2 Sieg) über 10 Bälle?", a:["Claudio Bravo","Marc-André ter Stegen","Neto","Jasper Cillessen"], c:1, d:"Mittel"},
{q:"Wer war der sportliche Leiter beim Bau des MSN-Trios?", a:["Andoni Zubizarreta","Eric Abidal","Mateu Alemany","Ramon Planes"], c:0, d:"Schwer"},
{q:"Welcher Brasilianer kam 2017 als 'Ersatz' für Neymar für 145 Mio.?", a:["Philippe Coutinho","Malcom","Arthur Melo","Paulinho"], c:0, d:"Leicht"},
{q:"Gegen wen verlor Barca 2019 das Halbfinale trotz 3:0 Hinspielsieg?", a:["FC Liverpool","AS Rom","FC Bayern","Real Madrid"], c:0, d:"Leicht"},
{q:"Wer ist der Spieler mit den zweitmeisten Einsätzen nach Messi?", a:["Xavi","Sergio Busquets","Andrés Iniesta","Carles Puyol"], c:1, d:"Schwer"},
{q:"Welche Nummer trägt Pedri aktuell (seit 2022)?", a:["Nr. 16","Nr. 8","Nr. 10","Nr. 21"], c:1, d:"Mittel"},
{q:"Wer war der Präsident während des zweiten Triples (2015)?", a:["Joan Laporta","Josep Maria Bartomeu","Sandro Rosell","Carles Tusquets"], c:1, d:"Schwer"},
{q:"Welcher Deutsche wechselte 2023 von Manchester City zu Barca?", a:["İlkay Gündoğan","Leroy Sané","Joshua Kimmich","Timo Werner"], c:0, d:"Leicht"},
{q:"Wie hieß der Brasilianer, der 2017 aus China kam und Kritiker verstummen ließ?", a:["Paulinho","Oscar","Hulk","Talisca"], c:0, d:"Schwer"}
]
};
let pool = []; let cur = 0; let score = 0;
function startQuiz(era) {
document.getElementById('menu-screen').style.display = 'none';
document.getElementById('quiz-card').style.display = 'flex';
document.getElementById('era-label').innerText = era === '90' ? '90ER JAHRE' : era === '00' ? '00ER JAHRE' : 'MODERNE';
pool = questions[era].sort(() => Math.random() - 0.5).slice(0, 20);
cur = 0; score = 0;
show();
}
function show() {
const q = pool[cur];
document.getElementById('progress').innerText = `${cur + 1} / 20`;
document.getElementById('q-text').innerText = q.q;
const dt = document.getElementById('diff-tag');
dt.innerText = q.d;
dt.className = 'difficulty-badge ' + (q.d === 'Leicht' ? 'diff-leicht' : q.d === 'Mittel' ? 'diff-mittel' : 'diff-schwer');
const cont = document.getElementById('opt-container');
cont.innerHTML = "";
q.a.forEach((o, i) => {
const b = document.createElement('button');
b.className = 'opt'; b.innerText = o;
b.onclick = () => {
const btns = document.querySelectorAll('.opt');
btns.forEach(x => x.disabled = true);
if(i === q.c) { b.classList.add('correct'); score++; }
else { b.classList.add('wrong'); btns[q.c].classList.add('correct'); }
setTimeout(() => { cur++; if(cur < 20) show(); else finish(); }, 1200);
};
cont.appendChild(b);
});
}
function finish() {
document.getElementById('quiz-main').style.display = 'none';
document.getElementById('slot-screen').style.display = 'block';
document.getElementById('final-score').innerText = score;
}
function runSlot() {
const s = document.getElementById('slot-val');
const l = document.getElementById('lever');
l.style.pointerEvents = 'none'; l.style.opacity = '0.5';
const r = ["FAN", "PLAYER", "LEGEND", "GOAT"];
let c = 0;
let t = setInterval(() => { s.innerText = r[c % r.length]; c++; }, 80);
setTimeout(() => {
clearInterval(t);
let rankId = 0; let finalName = "";
if(score >= 19) { rankId = 4; finalName = "THE GOAT 🐐"; }
else if(score >= 16) { rankId = 3; finalName = "BARÇA LEGENDE 🏆"; }
else if(score >= 12) { rankId = 2; finalName = "STAMMSPIELER ⚽"; }
else if(score >= 6) { rankId = 1; finalName = "TREUER FAN 🏟️"; }
else { rankId = 0; finalName = "PLASTIKFAN 🤡"; }
s.innerText = finalName;
document.getElementById(`r-${rankId}`).classList.add('rank-active');
}, 2000);
}
</script>
</body>
</html>

612
games/fussball.html Normal file
View File

@@ -0,0 +1,612 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Elfmeterschießen Simulator</title>
<style>
body {
margin: 0;
padding: 0;
background-color: #222;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
overflow: hidden;
}
#game-container {
position: relative;
box-shadow: 0 10px 30px rgba(0,0,0,0.5);
border: 4px solid #fff;
border-radius: 8px;
overflow: hidden;
}
canvas {
display: block;
background: linear-gradient(to bottom, #87CEEB 0%, #87CEEB 30%, #2E8B57 30%, #228B22 100%);
cursor: crosshair;
}
#ui-overlay {
position: absolute;
top: 20px;
left: 0;
width: 100%;
text-align: center;
pointer-events: none;
text-shadow: 2px 2px 4px rgba(0,0,0,0.8);
}
h1 {
margin: 0;
font-size: 24px;
text-transform: uppercase;
letter-spacing: 2px;
}
#score-board {
font-size: 18px;
margin-top: 5px;
font-weight: bold;
color: #ffeb3b;
}
#message {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 48px;
font-weight: 900;
opacity: 0;
transition: opacity 0.3s;
text-shadow: 0 0 10px rgba(0,0,0,0.5);
pointer-events: none;
}
.instruction {
position: absolute;
bottom: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
pointer-events: none;
}
</style>
</head>
<body>
<div id="game-container">
<canvas id="gameCanvas" width="800" height="600"></canvas>
<div id="ui-overlay">
<h1>Elfmeter Simulator</h1>
<div id="score-board">Tore: 0 | Versuche: 0</div>
</div>
<div id="message">TOOR!</div>
<div class="instruction">Klicke irgendwo ins Tor, um zu schießen!</div>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const messageEl = document.getElementById('message');
const scoreEl = document.getElementById('score-board');
// Zuschauer-Daten (statisch)
const spectators = [];
// Spielzustand
let score = 0;
let attempts = 0;
let isBallFlying = false;
let showMessageTimer = null;
let frameCount = 0; // Für Animationen
// Ball Physik
const startBallY = 520;
const startBallX = 400;
const ball = {
x: startBallX,
y: startBallY,
z: 0,
radius: 15,
targetX: 0,
targetY: 0,
speed: 0
};
// Torwart (Verbessert)
const goalie = {
x: 400,
baseY: 230, // Bodenlinie
y: 230, // Aktuelle Y Position
width: 50, // Körperbreite
height: 90,
speed: 1.5,
direction: 1,
diveTargetX: 0,
diveTargetY: 0,
isDiving: false,
angle: 0 // Rotation für Hechtsprung
};
// Tordimensionen
const goal = {
topY: 130,
bottomY: 230,
topLeftX: 250,
topRightX: 550,
bottomLeftX: 230,
bottomRightX: 570
};
// Hilfsfunktionen
function initSpectators() {
for (let y = 55; y < 220; y += 20) {
for (let x = 10; x < canvas.width; x += 15 + Math.random() * 10) {
spectators.push({
x: x,
y: y,
color: `hsl(${Math.random() * 360}, 70%, 60%)`
});
}
}
}
function resetBall() {
isBallFlying = false;
ball.x = startBallX;
ball.y = startBallY;
ball.z = 0;
ball.radius = 15;
// Torwart zurücksetzen
goalie.isDiving = false;
goalie.x = 400;
goalie.y = goalie.baseY;
goalie.angle = 0;
}
function showStatus(text, color) {
messageEl.innerText = text;
messageEl.style.color = color;
messageEl.style.opacity = 1;
clearTimeout(showMessageTimer);
showMessageTimer = setTimeout(() => {
messageEl.style.opacity = 0;
resetBall();
}, 2000);
}
function updateScore() {
scoreEl.innerText = `Tore: ${score} | Versuche: ${attempts}`;
}
// --- Zeichnen ---
function drawStands() {
ctx.fillStyle = "#555";
ctx.fillRect(0, 50, canvas.width, 180);
ctx.fillStyle = "#777";
for (let y = 60; y < 230; y += 20) {
ctx.fillRect(0, y, canvas.width, 10);
}
for (const spectator of spectators) {
ctx.fillStyle = spectator.color;
ctx.beginPath();
ctx.arc(spectator.x, spectator.y, 5, 0, Math.PI * 2);
ctx.fill();
}
ctx.fillStyle = "#333";
ctx.fillRect(0, 0, canvas.width, 50);
ctx.strokeStyle = "#222";
ctx.lineWidth = 5;
ctx.beginPath();
ctx.moveTo(0, 50);
ctx.lineTo(canvas.width, 50);
ctx.stroke();
}
function drawPitch() {
ctx.strokeStyle = "rgba(255, 255, 255, 0.2)";
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(100, 600);
ctx.lineTo(200, 230);
ctx.lineTo(600, 230);
ctx.lineTo(700, 600);
ctx.stroke();
ctx.fillStyle = "white";
ctx.beginPath();
ctx.arc(400, 480, 3, 0, Math.PI * 2);
ctx.fill();
}
function drawGoal() {
ctx.strokeStyle = "white";
ctx.lineWidth = 8;
ctx.lineJoin = "round";
ctx.beginPath();
ctx.moveTo(goal.topLeftX + 20, goal.topY - 10);
ctx.lineTo(goal.topRightX - 20, goal.topY - 10);
ctx.lineTo(goal.bottomRightX - 10, goal.bottomY);
ctx.moveTo(goal.topLeftX + 20, goal.topY - 10);
ctx.lineTo(goal.bottomLeftX + 10, goal.bottomY);
ctx.stroke();
ctx.strokeStyle = "rgba(255, 255, 255, 0.3)";
ctx.lineWidth = 1;
for (let i = goal.topLeftX; i < goal.topRightX; i += 20) {
ctx.beginPath();
ctx.moveTo(i, goal.topY);
ctx.lineTo(i + (i - 400) * 0.2, goal.bottomY);
ctx.stroke();
}
for (let j = goal.topY; j < goal.bottomY; j += 15) {
ctx.beginPath();
ctx.moveTo(goal.topLeftX, j);
ctx.lineTo(goal.topRightX, j);
ctx.stroke();
}
ctx.strokeStyle = "white";
ctx.lineWidth = 8;
ctx.beginPath();
ctx.moveTo(goal.bottomLeftX, goal.bottomY);
ctx.lineTo(goal.topLeftX, goal.topY);
ctx.lineTo(goal.topRightX, goal.topY);
ctx.lineTo(goal.bottomRightX, goal.bottomY);
ctx.stroke();
}
function drawGoalie() {
ctx.save();
// Position setzen (Mitte des Torsos ca.)
let drawX = goalie.x;
let drawY = goalie.y - 45; // Etwas höher als die Füße
ctx.translate(drawX, drawY);
ctx.rotate(goalie.angle); // Rotation für Hechtsprung
// Farben
const skinColor = "#ffccaa";
const shirtColor = "#FFD700"; // Gelb
const shortsColor = "#111"; // Schwarz
// --- Zeichne Körperteile (Menschlicher) ---
// Kopf
ctx.fillStyle = skinColor;
ctx.beginPath();
ctx.arc(0, -35, 12, 0, Math.PI * 2); // Relativ zur Mitte
ctx.fill();
// Körper (Trikot)
ctx.fillStyle = shirtColor;
// Abgerundetes Rechteck für Torso
ctx.beginPath();
ctx.roundRect(-18, -25, 36, 45, 5);
ctx.fill();
// Hose
ctx.fillStyle = shortsColor;
ctx.beginPath();
ctx.roundRect(-18, 15, 36, 15, 5);
ctx.fill();
// Gliedmaßen Animation
ctx.lineCap = "round";
ctx.lineJoin = "round";
// Beine
ctx.strokeStyle = skinColor; // Beine Hautfarbe oder Socken? Sagen wir schwarz für Stutzen
ctx.lineWidth = 10;
ctx.strokeStyle = "#111"; // Stutzen/Hose Verlängerung
ctx.beginPath();
if (goalie.isDiving) {
// Beine strecken beim Sprung
ctx.moveTo(-10, 30); ctx.lineTo(-15, 60); // Linkes Bein
ctx.moveTo(10, 30); ctx.lineTo(15, 60); // Rechtes Bein
} else {
// Beine leicht gebeugt beim Stehen (Idle Animation)
const kneeBend = Math.sin(frameCount * 0.1) * 2;
ctx.moveTo(-10, 30); ctx.lineTo(-12, 55 + kneeBend);
ctx.moveTo(10, 30); ctx.lineTo(12, 55 + kneeBend);
}
ctx.stroke();
// Arme (Trikot Farbe Ärmel + Haut)
// Wir zeichnen vereinfacht ganze Arme in Hautfarbe mit gelben Ärmeln
// Ärmel
ctx.strokeStyle = shirtColor;
ctx.lineWidth = 12;
ctx.beginPath();
ctx.moveTo(-15, -20); ctx.lineTo(-25, -5); // Links
ctx.moveTo(15, -20); ctx.lineTo(25, -5); // Rechts
ctx.stroke();
// Unterarme / Hände
ctx.strokeStyle = skinColor;
ctx.lineWidth = 10;
ctx.beginPath();
if (goalie.isDiving) {
// Arme weit strecken zum Ball
// Wenn wir nach rechts springen (angle > 0), ist "oben" relativ zur Rotation
// Da wir das ganze Canvas rotiert haben, zeichnen wir einfach Arme nach "oben" (über den Kopf)
ctx.moveTo(-25, -5); ctx.lineTo(-35, -40); // Arme hochreißen
ctx.moveTo(25, -5); ctx.lineTo(35, -40);
// Handschuhe (Weiß)
ctx.strokeStyle = "white";
ctx.lineWidth = 14;
ctx.beginPath();
ctx.moveTo(-35, -40); ctx.lineTo(-37, -45);
ctx.moveTo(35, -40); ctx.lineTo(37, -45);
ctx.stroke();
} else {
// Arme bereit halten (Idle)
const armWave = Math.cos(frameCount * 0.1) * 3;
ctx.moveTo(-25, -5); ctx.lineTo(-35 - armWave, 10);
ctx.moveTo(25, -5); ctx.lineTo(35 + armWave, 10);
// Handschuhe
ctx.strokeStyle = "white";
ctx.lineWidth = 14;
ctx.beginPath();
ctx.moveTo(-35 - armWave, 10); ctx.lineTo(-37 - armWave, 15);
ctx.moveTo(35 + armWave, 10); ctx.lineTo(37 + armWave, 15);
ctx.stroke();
}
ctx.stroke();
ctx.restore();
}
function drawBall() {
ctx.save();
ctx.translate(ball.x, ball.y);
if (isBallFlying) {
const rotation = Date.now() / 100;
ctx.rotate(rotation);
}
ctx.fillStyle = "white";
ctx.beginPath();
ctx.arc(0, 0, ball.radius, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = "black";
ctx.beginPath();
ctx.arc(0, 0, ball.radius * 0.5, 0, Math.PI * 2, false);
ctx.fill();
for(let i=0; i<5; i++) {
ctx.beginPath();
ctx.arc(
Math.cos(i * 2 * Math.PI / 5) * ball.radius * 0.7,
Math.sin(i * 2 * Math.PI / 5) * ball.radius * 0.7,
ball.radius * 0.2, 0, Math.PI*2
);
ctx.fill();
}
if (!isBallFlying || ball.z < 0.1) {
ctx.restore();
ctx.fillStyle = "rgba(0,0,0,0.3)";
ctx.beginPath();
ctx.ellipse(ball.x + 5, ball.y + ball.radius + 2, ball.radius, ball.radius * 0.3, 0, 0, Math.PI * 2);
ctx.fill();
} else {
ctx.restore();
}
}
// --- Logik ---
function update() {
frameCount++;
// Torwart Idle Bewegung (Automatisch hin und her)
if (!isBallFlying && !goalie.isDiving) {
goalie.x += goalie.speed * goalie.direction;
// Leichte Wippbewegung im Stand
goalie.y = goalie.baseY + Math.sin(frameCount * 0.2) * 2;
goalie.angle = 0; // Aufrecht stehen
if (goalie.x > goal.bottomRightX - 40 || goalie.x < goal.bottomLeftX + 40) {
goalie.direction *= -1;
}
}
else if (isBallFlying && goalie.isDiving) {
// HECHT-LOGIK
// X Bewegung
const dx = goalie.diveTargetX - goalie.x;
goalie.x += dx * 0.08; // Sanfteres Gleiten
// Y Bewegung (Sprung)
const dy = goalie.diveTargetY - goalie.y;
goalie.y += dy * 0.08;
// Rotation berechnen (Hecht)
// Wenn er weit zur Seite muss (>50px vom Zentrum), dreht er sich
const distFromCenter = goalie.diveTargetX - 400;
let targetAngle = 0;
if (Math.abs(distFromCenter) > 40) {
// 90 Grad (PI/2) nach rechts oder links
// Wir nehmen etwas weniger als 90 Grad für realistischeren Sprung (ca 70 Grad)
targetAngle = (distFromCenter > 0) ? 1.2 : -1.2;
} else {
// Bei zentralen Bällen nur leicht neigen oder aufrecht bleiben
targetAngle = (distFromCenter > 0) ? 0.2 : -0.2;
}
// Winkel interpolieren
goalie.angle += (targetAngle - goalie.angle) * 0.1;
}
// Ball Bewegung
if (isBallFlying) {
ball.z += 0.05;
const progress = ball.z;
ball.x = startBallX + (ball.targetX - startBallX) * progress;
ball.y = startBallY + (ball.targetY - startBallY) * progress;
ball.radius = 15 - (7 * progress);
if (progress >= 1) {
isBallFlying = false;
checkResult();
}
}
}
function checkResult() {
// Verbesserte Kollisionserkennung für den neuen Körper
// Wir prüfen die Distanz zum Zentrum des Torsos
// Da er sich dreht, ist eine einfache Box schwer, wir nehmen eine etwas größere Kreis-Distanz an
// Torso Position anpassen für Hitbox
let hitX = goalie.x;
let hitY = goalie.y - 40; // Körpermitte
const distX = Math.abs(ball.x - hitX);
const distY = Math.abs(ball.y - hitY);
// Hitbox
let caught = false;
// Körpertreffer
if (distX < 45 && distY < 45) caught = true;
// Optional: Wenn er hechtet, deckt er mehr Breite aber weniger Höhe ab
// Das simulieren wir einfachheitshalber über den distX Parameter oben, der schon relativ generisch ist.
if (caught) {
showStatus("GEHALTEN!", "#ff4444");
return;
}
// Tor Check
const inGoalX = ball.x > goal.topLeftX && ball.x < goal.topRightX;
const inGoalY = ball.y > goal.topY && ball.y < goal.bottomY;
if (inGoalX && inGoalY) {
score++;
showStatus("TOOOOR!", "#44ff44");
} else {
showStatus("VORBEI!", "#aaaaaa");
}
updateScore();
}
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawStands();
// Boden
ctx.fillStyle = "#2E8B57";
ctx.fillRect(0, 230, canvas.width, canvas.height - 230);
drawPitch();
drawGoal();
// Torwart zeichnen (Reihenfolge wichtig für Tiefe)
// Wenn Ball hinten ist (z nahe 1), ist Ball HINTER Torwart? Nein, Ball fliegt auf Tor zu.
// Im echten Leben steht Torwart VOR der Linie.
// Also: Ball (wenn weit weg) -> Torwart -> Ball (wenn nah)
// Hier einfachheitshalber: Torwart vor Netz, Ball davor.
drawGoalie();
drawBall();
update();
requestAnimationFrame(gameLoop);
}
// Input Handler
function handleInput(x, y) {
if (isBallFlying || messageEl.style.opacity == "1") return;
isBallFlying = true;
attempts++;
updateScore();
ball.targetX = x;
ball.targetY = y;
// KI Entscheidung
goalie.isDiving = true;
// Fehlerquote
const errorMargin = (Math.random() * 200) - 100;
// Ziel für den Torwart setzen
goalie.diveTargetX = ball.targetX + errorMargin;
// Er soll auch springen (Y-Achse)!
// Ziel-Y ist Ballhöhe, aber begrenzt durch Boden
// Wir addieren etwas Offset, da er "hoch" springen muss um an hohe Bälle zu kommen
let jumpHeight = ball.targetY;
if (jumpHeight > goalie.baseY) jumpHeight = goalie.baseY; // Nicht in den Boden graben
goalie.diveTargetY = jumpHeight + 40; // +40 weil seine Koordinaten bei den Füßen sind
// Begrenzen
if (goalie.diveTargetX < goal.bottomLeftX - 50) goalie.diveTargetX = goal.bottomLeftX - 50;
if (goalie.diveTargetX > goal.bottomRightX + 50) goalie.diveTargetX = goal.bottomRightX + 50;
}
canvas.addEventListener('mousedown', (e) => {
const rect = canvas.getBoundingClientRect();
const scaleX = canvas.width / rect.width;
const scaleY = canvas.height / rect.height;
const clickX = (e.clientX - rect.left) * scaleX;
const clickY = (e.clientY - rect.top) * scaleY;
handleInput(clickX, clickY);
});
canvas.addEventListener('touchstart', (e) => {
e.preventDefault();
const rect = canvas.getBoundingClientRect();
const scaleX = canvas.width / rect.width;
const scaleY = canvas.height / rect.height;
const touch = e.touches[0];
const clickX = (touch.clientX - rect.left) * scaleX;
const clickY = (touch.clientY - rect.top) * scaleY;
handleInput(clickX, clickY);
}, {passive: false});
initSpectators();
updateScore();
gameLoop();
</script>
</body>
</html>

View File

@@ -3,6 +3,8 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@700&display=swap">
<title>Helios Arcade</title> <title>Helios Arcade</title>
<style> <style>
/* --- Grundlegendes Styling & Reset --- */ /* --- Grundlegendes Styling & Reset --- */
@@ -10,11 +12,11 @@
box-sizing: border-box; box-sizing: border-box;
margin: 0; margin: 0;
padding: 0; padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; font-family: 'JetBrains Mono', monospace;
} }
body { body {
background-color: #121212; /* Sehr dunkles Grau, fast Schwarz */ background-color: #1e1e1e; /* Sehr dunkles Grau, fast Schwarz */
color: #ffffff; color: #ffffff;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -54,7 +56,7 @@
border: 1px solid #333; border: 1px solid #333;
border-radius: 8px; border-radius: 8px;
padding: 15px 20px; padding: 15px 20px;
font-family: 'Courier New', Courier, monospace; font-family: 'JetBrains Mono', monospace;
width: 100%; width: 100%;
max-width: 700px; max-width: 700px;
margin-bottom: 50px; margin-bottom: 50px;
@@ -69,21 +71,6 @@
color: #22c55e; /* Terminal Grün */ color: #22c55e; /* Terminal Grün */
} }
.cursor {
display: inline-block;
width: 8px;
height: 18px;
background-color: #ccc;
animation: blink 1s infinite;
vertical-align: middle;
margin-left: 5px;
}
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
/* --- Grid für die Spiele --- */ /* --- Grid für die Spiele --- */
.games-grid { .games-grid {
display: grid; display: grid;
@@ -167,21 +154,21 @@
</p> </p>
<div class="terminal-container"> <div class="terminal-container">
<span class="prompt">[gast@helios arcade ~]$</span> <span class="path">[</span><span class="prompt">gast@helios arcade</span> <span class="path">~]$</span>
<span class="terminal-text">./list-games.sh --all</span><span class="cursor"></span> <span class="terminal-text">./list-games.sh --all</span>
</div> </div>
<div class="games-grid"> <div class="games-grid">
<a href="starwars.html" class="game-card star-wars"> <a href="starwars.html" class="game-card star-wars">
<div class="icon-box">🚀</div> <div class="card-content"> <div class="icon-box"><i class="fa-solid fa-jedi"></i></div> <div class="card-content">
<h3>Trench Run</h3> <h3>Trench Run</h3>
<span>Star Wars Simulation</span> <span>Star Wars Simulation</span>
</div> </div>
</a> </a>
<a href="fussball.html" class="game-card football"> <a href="fussball.html" class="game-card football">
<div class="icon-box"></div> <div class="icon-box"><i class="fa-solid fa-futbol"></i></div>
<div class="card-content"> <div class="card-content">
<h3>Penalty Shootout</h3> <h3>Penalty Shootout</h3>
<span>Fussball Arcade</span> <span>Fussball Arcade</span>
@@ -189,13 +176,21 @@
</a> </a>
<a href="schach.html" class="game-card chess"> <a href="schach.html" class="game-card chess">
<div class="icon-box">♟️</div> <div class="icon-box"><i class="fa-solid fa-chess"></i></div>
<div class="card-content"> <div class="card-content">
<h3>Meister Schach</h3> <h3>Meister Schach</h3>
<span>Strategie & Logik</span> <span>Strategie & Logik</span>
</div> </div>
</a> </a>
<a href="barcafinal.html" class="game-card chess">
<div class="icon-box"><i class="fa-solid fa-futbol"></i></div>
<div class="card-content">
<h3>Barcelona Quiz</h3>
<span>Quiz & Rätsel</span>
</div>
</a>
<div class="game-card future" style="cursor: default; opacity: 0.7;"> <div class="game-card future" style="cursor: default; opacity: 0.7;">
<div class="icon-box">?</div> <div class="icon-box">?</div>
<div class="card-content"> <div class="card-content">
@@ -206,7 +201,7 @@
</div> </div>
<a href="index.html" class="back-link">← Zurück zum Dashboard</a> <a href="../index.html" class="back-link">← Zurück zum Dashboard</a>
</body> </body>
</html> </html>

View File

@@ -7,8 +7,13 @@
<link rel="icon" type="image/png" href="https://img.icons8.com/ios-filled/50/1793d1/sun--v1.png"> <link rel="icon" type="image/png" href="https://img.icons8.com/ios-filled/50/1793d1/sun--v1.png">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@700&display=swap">
<style> <style>
:root {
--text-color: #e0e0e0;
--accent-color: #1793d1;
}
/* Grundlayout */ /* Grundlayout */
body { body {
background-color: #1e1e1e; background-color: #1e1e1e;
@@ -25,27 +30,78 @@
width: 90%; width: 90%;
max-width: 800px; /* Nicht breiter als 800px */ max-width: 800px; /* Nicht breiter als 800px */
text-align: center; text-align: center;
padding-top: 50px; padding-top: 20px;
} }
/* Navigation oben rechts */ /* Navigation oben rechts */
.nav-bar { .top-nav {
position: absolute; position: absolute;
top: 20px; top: 20px;
right: 20px; right: 20px;
display: flex;
gap: 15px;
} }
.nav-link { .nav-link {
color: #888; color: var(--text-color);
font-size: 24px; font-size: 1.5rem;
padding: 10px;
border-radius: 50%;
transition: all 0.3s ease;
position: relative;
display: flex; /* Zum Zentrieren des Icons */
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
background-color: rgba(255, 255, 255, 0.05);
text-decoration: none; text-decoration: none;
transition: color 0.3s;
} }
.nav-link:hover { color: #1793d1; }
.nav-link:hover {
background-color: var(--accent-color);
color: #fff;
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(23, 147, 209, 0.4);
}
.nav-link::after {
content: attr(data-tooltip); /* Holt Text aus HTML attribute */
position: absolute;
bottom: -35px;
left: 50%;
transform: translateX(-50%);
background-color: #333;
color: #fff;
padding: 5px 10px;
border-radius: 4px;
font-size: 0.8rem;
opacity: 0;
visibility: hidden;
transition: opacity 0.3s;
white-space: nowrap;
pointer-events: none;
}
.nav-link:hover::after {
opacity: 1;
visibility: visible;
}
/* Texte */ /* Texte */
h1 { font-size: 3rem; margin-bottom: 10px; color: #fff; letter-spacing: 2px; } h1 {
.subtitle { color: #1793d1; font-weight: bold; text-transform: uppercase; font-size: 0.9rem; letter-spacing: 1px;} font-family: 'JetBrains Mono', monospace; /* Die neue Code-Schrift */
font-size: 4rem;
margin-bottom: 10px;
color: #fff;
letter-spacing: 4px;
/* Ein leichter Leuchteffekt passend zum Blau */
text-shadow: 0 0 10px rgba(23, 147, 209, 0.3), 0 0 20px rgba(23, 147, 209, 0.2);
min-height: 1.2em; /* Verhindert das Springen des Layouts */
display: flex;
justify-content: center;
align-items: center;
}
p { color: #aaa; line-height: 1.6; margin-bottom: 30px; } p { color: #aaa; line-height: 1.6; margin-bottom: 30px; }
/* Terminal Style */ /* Terminal Style */
@@ -53,20 +109,39 @@
background-color: #111; background-color: #111;
border-left: 3px solid #1793d1; border-left: 3px solid #1793d1;
padding: 20px; padding: 20px;
font-family: 'Courier New', monospace; font-family: 'JetBrains Mono', monospace;
text-align: left; text-align: left;
border-radius: 5px; border-radius: 5px;
margin-bottom: 50px; /* Abstand nach unten zu den Games */ margin-bottom: 50px; /* Abstand nach unten zu den Games */
box-shadow: 0 10px 30px rgba(0,0,0,0.5); box-shadow: 0 10px 30px rgba(0,0,0,0.5);
} }
/* Spezifische Farben für das Terminal-Banner */
.t-blue { color: #3498db; } /* Das Blau von ~]$ */
.t-yellow { color: #f1c40f; } /* Ein kräftiges Gelb für Symbole */
.t-white { color: #ffffff; } /* Reinweiß für den Rest */
.terminal pre {
margin: 0 0 20px 0;
font-family: 'JetBrains', monospace;
line-height: 1.2;
white-space: pre; /* Behält die Abstände der ASCII-Art bei */
}
.prompt { color: #2ecc71; } .prompt { color: #2ecc71; }
.path { color: #3498db; } .path { color: #3498db; }
.command { color: #e0e0e0; } .command { color: #e0e0e0; }
.cursor { .title-cursor {
display: inline-block; width: 8px; height: 15px; background: #e0e0e0; display: inline-block;
animation: blink 1s infinite; vertical-align: middle; color: var(--accent-color); /* Nutzt dein Helios-Blau */
margin-left: 5px;
animation: blink 1s infinite;
font-family: 'JetBrains Mono', monospace;
font-weight: 300; /* Etwas dünner sieht oft edler aus */
}
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
} }
@keyframes blink { 50% { opacity: 0; } }
/* --- NEU: DASHBOARD GRID FÜR SPIELE --- */ /* --- NEU: DASHBOARD GRID FÜR SPIELE --- */
.apps-title { .apps-title {
@@ -117,14 +192,14 @@
</head> </head>
<body> <body>
<div class="nav-bar" style="display: flex; gap: 20px;"> <div class="top-nav">
<a href="https://code.helios.giize.com" class="nav-link" data-tooltip="Code" target="_blank"> <a href="https://code.helios.giize.com" class="nav-link" data-tooltip="Code" target="_blank">
<i class="fa-solid fa-code"></i> <i class="fa-solid fa-code"></i>
</a> </a>
<a href="https://git.helios.giize.com" class="nav-link" data-tooptip="Gitea" target="_blank"> <a href="https://git.helios.giize.com" class="nav-link" data-tooltip="Gitea" target="_blank">
<i class="fa-brands fa-git-alt"></i> <i class="fa-brands fa-git-alt"></i>
</a> </a>
<a href="https://docker.helios.giize.com" class="nav-link" data-tooptip="Docker" target="_blank"> <a href="https://docker.helios.giize.com" class="nav-link" data-tooltip="Docker" target="_blank">
<i class="fa-brands fa-docker"></i> <i class="fa-brands fa-docker"></i>
</a> </a>
<a href="https://admin.helios.giize.com" class="nav-link" data-tooltip="Admin" target="_blank"> <a href="https://admin.helios.giize.com" class="nav-link" data-tooltip="Admin" target="_blank">
@@ -133,17 +208,21 @@
</div> </div>
<div class="container"> <div class="container">
<span class="subtitle">Status: Online</span> <h1><span id="typewriter"></span><span class="title-cursor">_</span></h1>
<h1>HELIOS</h1>
<p>
Große Dinge haben kleine Anfänge. Diese Präsenz befindet sich derzeit im Aufbau.
Schau später wieder vorbei, um Projekte rund um Entwicklung, Datenanalyse und mehr zu sehen.
</p>
<div class="terminal"> <div class="terminal">
<span class="prompt">[admin@helios</span> <span class="path">~]$</span> <pre>
<span class="command">./deploy-projects.sh --active</span><span class="cursor"></span> <span class="t-blue">SERVER STATS</span>
<span class="t-yellow">__ __ ___ -------------------------</span>
<span class="t-yellow">/ / / /__ / (_)___ _____</span> <span class="t-white">Users </span><span class="t-yellow">:</span> <span class="t-white" id="stat-users">0</span>
<span class="t-yellow">/ /_/ / _ \/ / / __ \/ ___/</span> <span class="t-white">Procs </span><span class="t-yellow">:</span> <span class="t-white" id="stat-procs">0</span>
<span class="t-yellow">/ __ / __/ / / /_/ (__ )</span> <span class="t-white">Load </span><span class="t-yellow">:</span> <span class="t-white" id="stat-load">0.0</span><span class="t-white">%</span>
<span class="t-yellow">/_/ /_/\___/_/_/\____/____/</span> <span class="t-white">Memory </span><span class="t-yellow">:</span> <span class="t-white" id="stat-memory">0.0</span><span class="t-white">%</span>
<span class="t-white">Disk </span><span class="t-yellow">:</span> <span class="t-white" id="stat-disk">0</span><span class="t-white">%</span></pre>
<span class="path">[</span><span class="prompt">admin@helios:</span> <span class="path">~]$</span>
<span class="command">./deploy-projects.sh --active</span>
</div> </div>
<h2 class="apps-title">Apps & Dashboard</h2> <h2 class="apps-title">Apps & Dashboard</h2>
@@ -158,7 +237,7 @@
</div> </div>
</a> </a>
<a href="/games/" class="app-card"> <a href="games/games_index.html" class="app-card">
<div class="app-icon icon-games">🕹️</div> <div class="app-icon icon-games">🕹️</div>
<div class="app-info"> <div class="app-info">
<h3>Arcade</h3> <h3>Arcade</h3>
@@ -170,8 +249,55 @@
<br><br><br> <br><br><br>
</div> </div>
<script>
const text = "Helios";
const speed = 150;
let i = 0;
// Funktion zum Hochzählen der Zahlen
function animateValue(id, start, end, duration, decimals = 0) {
const obj = document.getElementById(id);
const startTime = Date.now();
function update() {
const currentTime = Date.now();
const elapsed = currentTime - startTime;
const progress = Math.min(elapsed / duration, 1);
const currentVal = (progress * (end - start) + start).toFixed(decimals);
obj.innerHTML = currentVal;
if (progress < 1) {
requestAnimationFrame(update);
}
}
requestAnimationFrame(update);
}
function startStatsAnimation() {
// Hier definierst du Zielwerte, Dauer und Nachkommastellen
animateValue("stat-users", 0, 2, 1000, 0);
animateValue("stat-procs", 0, 186, 1200, 0);
animateValue("stat-load", 0, 14.3, 1500, 1);
animateValue("stat-memory", 0, 18.2, 1500, 1);
animateValue("stat-disk", 0, 6, 1500, 0);
}
function typeWriter() {
if (i < text.length) {
document.getElementById("typewriter").innerHTML += text.charAt(i);
i++;
setTimeout(typeWriter, speed);
} else {
// Wenn HELIOS fertig ist, starte die Zahlen-Animation
setTimeout(startStatsAnimation, 500); // Kurze Pause für den Effekt
}
}
// Beim Laden: Erst 800ms warten, dann Schreibmaschine starten
window.onload = () => {
setTimeout(typeWriter, 800);
};
</script>
</body> </body>
</html> </html>