Console
Clique sur « Exécuter » pour lancer le programme.
Code CoddyRun
@ CONFIGURATION
graph est une toile
dimension(graph, 640, 540)
COTE est un nombre
COTE vaut 15
// --- Curseur de construction (la camera le suit) ---
cX est un nombre
cY est un nombre
cX vaut 7
cY vaut 8
zoom est un nombre
zoom vaut 100
orientation est un nombre
orientation vaut 0
// --- Gestion du temps ---
temps est un nombre
temps vaut 0
compteurMois est un nombre
compteurMois vaut 0
dureeMois est un nombre
dureeMois vaut 100
// --- Les constructions ---
// numeros : 1 route, 2 residentiel, 3 commerce, 4 industrie, 5 centrale,
// 6 parc, 7 bosquet (nature), 8 ecole, 9 caserne de pompiers, 10 ruines, 11 banque,
// 12 parc d'attractions
// Le menu Construire (touche C) propose 10 choix (raccourcis : touches 1 a 9 et 0)
selBat est un tableau
selBat vaut [1, 2, 3, 4, 5, 6, 8, 9, 11, 12]
selCout est un tableau
selCout vaut [10, 35, 50, 65, 220, 30, 150, 120, 200, 300]
selNom est un tableau
selNom vaut ["Route", "Zone résidentielle", "Zone commerciale", "Zone industrielle", "Centrale électrique", "Parc public", "École", "Caserne de pompiers", "Banque", "Parc d'attractions"]
selCourt est un tableau
selCourt vaut ["Route", "Maisons", "Commerce", "Industrie", "Centrale", "Parc", "École", "Pompiers", "Banque", "Attractions"]
// population necessaire pour debloquer chaque construction
selDeb est un tableau
selDeb vaut [0, 0, 0, 0, 0, 0, 80, 120, 150, 60]
// entretien mensuel et description, pour le menu Construire
selEntr est un tableau
selEntr vaut ["0,25 €", "gratuit", "gratuit", "gratuit", "15 €", "2 €", "10 €", "8 €", "5 €", "10 €"]
selDescr est un tableau
selDescr vaut ["Relie les zones entre elles : indispensable pour grandir !", "Des maisons puis des immeubles. Ils paient la taxe d'habitation.", "Boutiques et bureaux : des emplois et la taxe commerciale.", "Usines : beaucoup d'emplois et la taxe industrielle, mais de la pollution.", "Alimente en électricité toutes les cases à 6 cases autour.", "Rend les habitants heureux, nettoie l'air, valorise le terrain.", "Rend les familles heureuses et permet de bâtir des immeubles.", "Éteint les incendies dans un rayon de 6 cases.", "Les habitants y placent leur argent : la ville touche des intérêts.", "Grande roue et manèges : les touristes dépensent leur argent ici !"]
selCoul est un tableau
selCoul ajoute #71717A
selCoul ajoute #4ADE80
selCoul ajoute #38BDF8
selCoul ajoute #FB923C
selCoul ajoute #CBD5E1
selCoul ajoute #16A34A
selCoul ajoute #DC2626
selCoul ajoute #EF4444
selCoul ajoute #FACC15
selCoul ajoute #EC4899
sel est un nombre
sel vaut 1
// --- Paliers : ta ville grandit ! ---
paliers est un tableau
paliers vaut [100, 250, 400, 600]
palNoms est un tableau
palNoms vaut ["Village", "Bourg", "Ville", "Métropole"]
palPrimes est un tableau
palPrimes vaut [150, 250, 400, 0]
palierIdx est un nombre
palierIdx vaut 0
// --- Tresorerie et statistiques ---
argent est un nombre
argent vaut 1000
mois est un nombre
mois vaut 1
annee est un nombre
annee vaut 1
// --- Les trois taxes (en %) ---
taxeHab est un nombre
taxeHab vaut 9
taxeCom est un nombre
taxeCom vaut 9
taxeInd est un nombre
taxeInd vaut 9
pop est un nombre
pop vaut 0
emplois est un nombre
emplois vaut 0
bonheur est un nombre
bonheur vaut 60
polTotal est un nombre
polTotal vaut 0
demR, demC, demI est un nombre
demR vaut 20
demC vaut 0
demI vaut 15
indicePop est un texte
indicePop vaut "Tout va bien"
nbIncendies est un nombre
nbIncendies vaut 0
fini est un booléen
fini vaut faux
reussite est un booléen
reussite vaut faux
message est un texte
message vaut "Trace des routes, pose des zones. Le temps passe tout seul !"
// --- Affichage ---
// vues : 0 normale, 1 electricite, 2 pollution, 3 valeur du terrain, 4 services
modeVue est un nombre
modeVue vaut 0
nomsVues est un tableau
nomsVues vaut ["Vue normale", "Vue : électricité", "Vue : pollution", "Vue : valeur du terrain", "Vue : écoles et pompiers"]
pinceau est un booléen
pinceau vaut faux
banniereTxt est un texte
banniereTxt vaut ""
banniereT est un nombre
banniereT vaut 0
gainTxt est un texte
gainTxt vaut ""
gainPositif est un booléen
gainPositif vaut vrai
gainT est un nombre
gainT vaut 0
// valeurs recalculees a chaque image par le processus
dxG, dyG, ech, phaseJour, ecX, ecY est un nombre
nuit est un booléen
nuit vaut faux
// lumieres de la nuit (fenetres, lampadaires, phares...)
lumX est un tableau
lumY est un tableau
lumR est un tableau
lumC est un tableau
// couleurs des voitures
couleursV est un tableau
couleursV ajoute #EF4444
couleursV ajoute #3B82F6
couleursV ajoute #F8FAFC
couleursV ajoute #FACC15
couleursV ajoute #22C55E
action est un nombre
// --- Menus et ecrans ---
// ecranActif : 0 titre, 1 jeu, 2 fin, 3 aide, 5 pause, 6 construire, 7 finances
ecranActif est un nombre
ecranActif vaut 0
ecranRetour est un nombre
ecranRetour vaut 0
menuSel est un nombre
menuSel vaut 0
pauseSel est un nombre
pauseSel vaut 0
pageAide est un nombre
pageAide vaut 0
tic est un nombre
tic vaut 0
enCours est un booléen
enCours vaut vrai
menuTitre est un tableau
menuTitre vaut ["Nouvelle partie", "Comment jouer", "Quitter"]
menuPause est un tableau
menuPause vaut ["Reprendre", "Comment jouer", "Menu principal"]
msgMenu est un texte
msgMenu vaut ""
// --- Credit bancaire : 500 EUR tout de suite, rembourses 50 EUR par mois pendant 11 mois ---
MONTANT_PRET est un nombre
MONTANT_PRET vaut 500
MENSUALITE est un nombre
MENSUALITE vaut 50
DUREE_PRET est un nombre
DUREE_PRET vaut 11
pretMois est un nombre
pretMois vaut 0
nbPrets est un nombre
nbPrets vaut 0
// --- La banque ---
// taux en % par mois
TAUX_DEPOTS est un nombre
TAUX_DEPOTS vaut 2
TAUX_EPARGNE est un nombre
TAUX_EPARGNE vaut 2
TAUX_AGIOS est un nombre
TAUX_AGIOS vaut 3
depotsHab est un nombre
depotsHab vaut 0
epargneVille est un nombre
epargneVille vaut 0
// le bilan du dernier mois, pour le menu Finances
dImpHab, dImpCom, dImpInd, dIntBanque, dIntEpargne, dEntretien, dCredit, dAgios est un nombre
dExport, dTourisme, dAide est un nombre
dExport vaut 0
dTourisme vaut 0
dAide vaut 0
// l'aide de l'Etat aux jeunes villes (pendant les 2 premieres annees)
AIDE_ETAT est un nombre
AIDE_ETAT vaut 60
dImpHab vaut 0
dImpCom vaut 0
dImpInd vaut 0
dIntBanque vaut 0
dIntEpargne vaut 0
dEntretien vaut 0
dCredit vaut 0
dAgios vaut 0
// menus de jeu : 6 Construire, 7 Finances
constrSel est un nombre
constrSel vaut 0
finSel est un nombre
finSel vaut 0
msgFin est un texte
msgFin vaut ""
// --- Historique de la population (36 derniers mois) ---
histPop est un tableau
// hauteurs des immeubles de l'ecran titre
skyH est un tableau
skyH vaut [70, 110, 55, 140, 90, 170, 60, 120, 85, 150, 65, 100, 130, 75, 160, 95]
@ GRILLES de LA VILLE
// toutes les grilles sont lues [ligne][colonne], c'est-a-dire [y][x]
bat est un tableau
niv est un tableau
alim est un tableau
pollu est un tableau
eco est un tableau
pomp est un tableau
val est un tableau
feu est un tableau
chantier est un tableau
pour i de 0 à COTE
lB est un tableau
lN est un tableau
lA est un tableau
lP est un tableau
lE est un tableau
lPo est un tableau
lV est un tableau
lF est un tableau
lCh est un tableau
pour j de 0 à COTE
lB ajoute 0
lN ajoute 0
lA ajoute faux
lP ajoute 0
lE ajoute faux
lPo ajoute faux
lV ajoute 0
lF ajoute 0
lCh ajoute 0
fin pour
bat ajoute lB
niv ajoute lN
alim ajoute lA
pollu ajoute lP
eco ajoute lE
pomp ajoute lPo
val ajoute lV
feu ajoute lF
chantier ajoute lCh
fin pour
@ LE TERRAIN de DEPART
procédure genererTerrain()
ki est un nombre
kj est un nombre
pour ki de 0 à COTE
pour kj de 0 à COTE
bat[ki][kj] vaut 0
niv[ki][kj] vaut 0
alim[ki][kj] vaut faux
pollu[ki][kj] vaut 0
eco[ki][kj] vaut faux
pomp[ki][kj] vaut faux
val[ki][kj] vaut 0
feu[ki][kj] vaut 0
chantier[ki][kj] vaut 0
fin pour
fin pour
// des bosquets
pour ki de 0 à COTE
pour kj de 0 à COTE
si hasard(1, 100) <= 12 alors
bat[ki][kj] vaut 7
fin si
fin pour
fin pour
pour ki de 7 à 9
pour kj de 7 à 9
bat[ki][kj] vaut 0
fin pour
fin pour
fin procédure
appelle genererTerrain()
@ OUTILS
// une case est-elle une route ? (on verifie d'abord qu'elle existe)
fonction estRoute(gx, gy)
si gx < 0 ou gx > COTE ou gy < 0 ou gy > COTE alors
retourne faux
fin si
retourne bat[gy][gx] = 1
fin fonction
// position a l'ecran d'une case de la grille (resultat dans ecX, ecY)
procédure versEcran(gx, gy)
ox est un nombre
ox vaut gx - cX
oy est un nombre
oy vaut gy - cY
vrx est un nombre
vry est un nombre
si orientation = 0 alors
vrx vaut ox
vry vaut oy
sinon si orientation = 1 alors
vrx vaut oy
vry vaut 0 - ox
sinon si orientation = 2 alors
vrx vaut 0 - ox
vry vaut 0 - oy
sinon
vrx vaut 0 - oy
vry vaut ox
fin si
ecX vaut 320 + (vrx - vry) * dxG
ecY vaut 270 + (vrx + vry) * dyG
fin procédure
procédure ajouterLumiere(lx, ly, lr, lc)
si longueur(lumX) < 140 alors
lumX ajoute lx
lumY ajoute ly
lumR ajoute lr
lumC ajoute lc
fin si
fin procédure
fonction peutConstruire()
ok est un booléen
ok vaut vrai
si bat[cY][cX] > 0 alors
ok vaut faux
sinon si argent < selCout[sel - 1] alors
ok vaut faux
sinon si pop < selDeb[sel - 1] alors
ok vaut faux
fin si
retourne ok
fin fonction
@ TUILE de TERRAIN
procédure dessinerSol(t, qx, qy, ddx, ddy, prof, cTop, cG, cD, cLigne)
contour(t, cLigne, 1)
polygone(t, [qx - ddx, qy, qx, qy + ddy, qx, qy + ddy + prof, qx - ddx, qy + prof], cG)
polygone(t, [qx, qy + ddy, qx + ddx, qy, qx + ddx, qy + prof, qx, qy + ddy + prof], cD)
polygone(t, [qx, qy - ddy, qx + ddx, qy, qx, qy + ddy, qx - ddx, qy], cTop)
contour(t, #0)
fin procédure
@ CUBE AVEC OMBRE PORTEE
procédure dessinerCube(t, qx, qy, ddx, ddy, h, cTop, cG, cD)
polygone(t, [qx - ddx, qy, qx, qy + ddy, qx + ddx + h / 3, qy - h / 5, qx + h / 3, qy - ddy - h / 5], rgba(0, 0, 0, 0.22))
contour(t, #1F2937, 1)
lCY est un nombre
lCY vaut qy - h
polygone(t, [qx - ddx, lCY, qx, lCY + ddy, qx, lCY + ddy + h, qx - ddx, lCY + h], cG)
polygone(t, [qx, lCY + ddy, qx + ddx, lCY, qx + ddx, lCY + h, qx, lCY + ddy + h], cD)
polygone(t, [qx, lCY - ddy, qx + ddx, lCY, qx, lCY + ddy, qx - ddx, lCY], cTop)
contour(t, #0)
fin procédure
// un toit en pointe pose sur un cube de hauteur h
procédure dessinerToit(t, qx, qy, ddx, ddy, h, hToit, cG, cD)
lCY est un nombre
lCY vaut qy - h
contour(t, #1F2937, 1)
polygone(t, [qx - ddx, lCY, qx, lCY + ddy, qx, lCY - hToit], cG)
polygone(t, [qx, lCY + ddy, qx + ddx, lCY, qx, lCY - hToit], cD)
contour(t, #0)
fin procédure
// des fenetres sur les deux faces visibles d'un cube
procédure dessinerFenetres(t, qx, qy, ddx, ddy, h, rangees, coul)
lCY est un nombre
lCY vaut qy - h
tf est un nombre
tf vaut maximum(2, 3 * ech)
kr est un nombre
pour kr de 0 à rangees - 1
v est un nombre
v vaut (kr + 0.5) / rangees
rectangle(t, qx - ddx + 0.3 * ddx - tf / 2, lCY + 0.3 * ddy + v * h - tf / 2, tf, tf, coul)
rectangle(t, qx - ddx + 0.7 * ddx - tf / 2, lCY + 0.7 * ddy + v * h - tf / 2, tf, tf, coul)
rectangle(t, qx + 0.3 * ddx - tf / 2, lCY + ddy - 0.3 * ddy + v * h - tf / 2, tf, tf, coul)
rectangle(t, qx + 0.7 * ddx - tf / 2, lCY + ddy - 0.7 * ddy + v * h - tf / 2, tf, tf, coul)
fin pour
fin procédure
@ LOSANGE de SURBRILLANCE
procédure dessinerLosange(t, qx, qy, ddx, ddy, coul, cLigne)
contour(t, cLigne, 2)
polygone(t, [qx, qy - ddy, qx + ddx, qy, qx, qy + ddy, qx - ddx, qy], coul)
contour(t, #0)
fin procédure
procédure dessinerFlammes(t, qx, qy, h)
e est un nombre
e vaut ech
vac est un nombre
vac vaut hasard(0, 3) * e
triangle(t, qx - 10 * e, qy - h, qx - 2 * e, qy - h, qx - 6 * e, qy - h - 16 * e - vac, #F97316)
triangle(t, qx - 3 * e, qy - h, qx + 7 * e, qy - h, qx + 2 * e, qy - h - 22 * e + vac, #EF4444)
triangle(t, qx + 4 * e, qy - h, qx + 11 * e, qy - h, qx + 8 * e, qy - h - 13 * e - vac, #FACC15)
cercle(t, qx + 2 * e, qy - h - 30 * e - (temps mod 10) * e, 6 * e, rgba(60, 60, 60, 0.5))
appelle ajouterLumiere(qx, qy - h - 8 * e, 30 * e, rgba(249, 115, 22, 0.22))
fin procédure
@ CONSTRUCTIONS et ANIMATIONS
procédure dessinerBatiment(t, qx, qy, b, n, gx, gy)
e est un nombre
e vaut ech
courant est un booléen
courant vaut alim[gy][gx]
allume est un booléen
allume vaut nuit et courant
h est un nombre
h vaut 0
fum est un nombre
cFen est un texte
si allume alors
cFen vaut #FEF08A
sinon si courant alors
cFen vaut #BFDBFE
sinon
cFen vaut #334155
fin si
// chantier en cours : echafaudages
si chantier[gy][gx] > 0 et b >= 2 alors
appelle dessinerCube(t, qx, qy, dxG * 0.6, dyG * 0.6, 6 * e, #D6D3D1, #A8A29E, #78716C)
ligne(t, qx - dxG * 0.6, qy - 20 * e, qx - dxG * 0.6, qy, #F59E0B, 2)
ligne(t, qx + dxG * 0.6, qy - 20 * e, qx + dxG * 0.6, qy, #F59E0B, 2)
ligne(t, qx - dxG * 0.6, qy - 20 * e, qx + dxG * 0.6, qy - 20 * e, #F59E0B, 2)
ligne(t, qx - dxG * 0.6, qy - 10 * e, qx + dxG * 0.6, qy - 10 * e, #F59E0B, 1)
// la grue
ligne(t, qx + 4 * e, qy, qx + 4 * e, qy - 34 * e, #FACC15, 2)
ligne(t, qx - 12 * e, qy - 34 * e, qx + 16 * e, qy - 34 * e, #FACC15, 2)
ligne(t, qx - 8 * e, qy - 34 * e, qx - 8 * e, qy - 24 * e + (temps mod 8) * e, #E5E7EB, 1)
sinon si b = 2 alors
// RESIDENTIEL : maisonnette, grande maison, puis immeuble
si n <= 1 alors
h vaut 10 * e
appelle dessinerCube(t, qx, qy, dxG * 0.5, dyG * 0.5, h, #FDE2C4, #F4C9A0, #E2B07F)
appelle dessinerToit(t, qx, qy, dxG * 0.5, dyG * 0.5, h, 10 * e, #DC2626, #B91C1C)
appelle dessinerFenetres(t, qx, qy, dxG * 0.5, dyG * 0.5, h, 1, cFen)
sinon si n = 2 alors
h vaut 18 * e
appelle dessinerCube(t, qx, qy, dxG * 0.66, dyG * 0.66, h, #E0F2FE, #CBD5E1, #94A3B8)
appelle dessinerToit(t, qx, qy, dxG * 0.66, dyG * 0.66, h, 12 * e, #475569, #334155)
appelle dessinerFenetres(t, qx, qy, dxG * 0.66, dyG * 0.66, h, 2, cFen)
sinon
h vaut 40 * e
appelle dessinerCube(t, qx, qy, dxG * 0.62, dyG * 0.62, h, #FCD34D, #FDE68A, #F59E0B)
appelle dessinerFenetres(t, qx, qy, dxG * 0.62, dyG * 0.62, h, 5, cFen)
rectangle(t, qx - 3 * e, qy - h - 6 * e, 6 * e, 5 * e, #78716C)
fin si
si allume alors
appelle ajouterLumiere(qx, qy - h / 2, 16 * e + n * 4 * e, rgba(254, 240, 138, 0.16))
fin si
sinon si b = 3 alors
// COMMERCE : boutique a auvent, galerie, tour de bureaux
si n <= 1 alors
h vaut 12 * e
appelle dessinerCube(t, qx, qy, dxG * 0.6, dyG * 0.6, h, #BAE6FD, #7DD3FC, #38BDF8)
polygone(t, [qx - dxG * 0.6, qy - h * 0.55, qx, qy - h * 0.55 + dyG * 0.6, qx, qy - h * 0.55 + dyG * 0.6 + 4 * e, qx - dxG * 0.6, qy - h * 0.55 + 4 * e], #EF4444)
polygone(t, [qx, qy - h * 0.55 + dyG * 0.6, qx + dxG * 0.6, qy - h * 0.55, qx + dxG * 0.6, qy - h * 0.55 + 4 * e, qx, qy - h * 0.55 + dyG * 0.6 + 4 * e], #F8FAFC)
sinon si n = 2 alors
h vaut 18 * e
appelle dessinerCube(t, qx, qy, dxG * 0.8, dyG * 0.8, h, #99F6E4, #5EEAD4, #14B8A6)
appelle dessinerFenetres(t, qx, qy, dxG * 0.8, dyG * 0.8, h, 2, cFen)
sinon
h vaut 52 * e
appelle dessinerCube(t, qx, qy, dxG * 0.55, dyG * 0.55, h, #93C5FD, #60A5FA, #2563EB)
kb est un nombre
pour kb de 1 à 6
ligne(t, qx - dxG * 0.55, qy - h + kb * h / 7, qx, qy - h + kb * h / 7 + dyG * 0.55, rgba(255, 255, 255, 0.35), 1)
ligne(t, qx, qy - h + kb * h / 7 + dyG * 0.55, qx + dxG * 0.55, qy - h + kb * h / 7, rgba(255, 255, 255, 0.25), 1)
fin pour
ligne(t, qx, qy - h - dyG * 0.55, qx, qy - h - dyG * 0.55 - 12 * e, #94A3B8, 2)
si nuit et temps mod 6 < 3 alors
cercle(t, qx, qy - h - dyG * 0.55 - 12 * e, 2 * e, #EF4444)
appelle ajouterLumiere(qx, qy - h - dyG * 0.55 - 12 * e, 8 * e, rgba(239, 68, 68, 0.35))
fin si
fin si
si allume alors
appelle ajouterLumiere(qx, qy - h / 2, 18 * e + n * 4 * e, rgba(186, 230, 253, 0.16))
fin si
sinon si b = 4 alors
// INDUSTRIE : usine a toit en dents de scie et cheminees qui fument
h vaut 11 * e + n * 4 * e
appelle dessinerCube(t, qx, qy, dxG * 0.8, dyG * 0.8, h, #FDBA74, #EA580C, #C2410C)
kd est un nombre
pour kd de 0 à 2
tx est un nombre
tx vaut qx - dxG * 0.8 + (kd + 0.5) * dxG * 0.53
ty est un nombre
ty vaut qy - h + (kd + 0.5) * dyG * 0.53 - dyG * 0.25
triangle(t, tx - 6 * e, ty + 3 * e, tx + 6 * e, ty + 3 * e, tx + 6 * e, ty - 6 * e, #9A3412)
fin pour
kc est un nombre
pour kc de 1 à n
chx est un nombre
chx vaut qx + 3 * e + (kc - 1) * 7 * e
rectangle(t, chx, qy - h - 14 * e, 4 * e, 16 * e, #57534E)
fum vaut (temps * 2 + kc * 5) mod 18
cercle(t, chx + 2 * e, qy - h - 18 * e - fum * e, (4 + fum / 4) * e, rgba(148, 163, 184, 0.55 - fum / 40))
fin pour
si allume alors
appelle ajouterLumiere(qx, qy - h / 2, 18 * e, rgba(253, 186, 116, 0.14))
fin si
sinon si b = 5 alors
// CENTRALE : batiment + tour de refroidissement
appelle dessinerCube(t, qx - 6 * e, qy + 2 * e, dxG * 0.55, dyG * 0.55, 18 * e, #CBD5E1, #94A3B8, #64748B)
rectangle(t, qx - 14 * e, qy - 10 * e, 14 * e, 3 * e, #EF4444)
polygone(t, [qx + 4 * e, qy + 2 * e, qx + 22 * e, qy + 2 * e, qx + 18 * e, qy - 30 * e, qx + 8 * e, qy - 30 * e], #E2E8F0)
ellipse(t, qx + 13 * e, qy - 30 * e, 5 * e, 2 * e, #94A3B8)
fum vaut (temps * 2) mod 20
cercle(t, qx + 13 * e, qy - 36 * e - fum * e, (6 + fum / 3) * e, rgba(241, 245, 249, 0.55 - fum / 45))
cercle(t, qx + 17 * e, qy - 46 * e - fum * e, (8 + fum / 3) * e, rgba(241, 245, 249, 0.35 - fum / 60))
si nuit alors
appelle ajouterLumiere(qx, qy - 12 * e, 26 * e, rgba(125, 211, 252, 0.15))
fin si
sinon si b = 6 alors
// PARC : pelouse, arbres et fontaine qui jaillit
appelle dessinerLosange(t, qx, qy, dxG * 0.85, dyG * 0.85, #4ADE80, #22C55E)
rectangle(t, qx - 8 * e, qy - 4 * e, 3 * e, 4 * e, #78350F)
cercle(t, qx - 7 * e, qy - 9 * e, 6 * e, #16A34A)
rectangle(t, qx + 6 * e, qy - 6 * e, 3 * e, 6 * e, #78350F)
cercle(t, qx + 7 * e, qy - 12 * e, 7 * e, #22C55E)
ellipse(t, qx, qy + 2 * e, 6 * e, 3 * e, #38BDF8)
jet est un nombre
jet vaut (temps mod 4) * e
ligne(t, qx, qy + 1 * e, qx, qy - 5 * e - jet, #BAE6FD, 2)
cercle(t, qx - 2 * e, qy - 3 * e - jet / 2, 1 * e, #E0F2FE)
cercle(t, qx + 2 * e, qy - 2 * e - jet / 2, 1 * e, #E0F2FE)
si nuit alors
appelle ajouterLumiere(qx, qy, 14 * e, rgba(134, 239, 172, 0.12))
fin si
sinon si b = 7 alors
// BOSQUET : les arbres se balancent doucement
bal est un nombre
bal vaut sinus(radians(temps * 12 + gx * 40 + gy * 25)) * 1.5 * e
rectangle(t, qx - 2 * e, qy - 12 * e, 4 * e, 12 * e, #78350F)
cercle(t, qx + bal, qy - 19 * e, 9 * e, #15803D)
cercle(t, qx - 5 * e + bal, qy - 14 * e, 6 * e, #166534)
cercle(t, qx + 6 * e + bal, qy - 15 * e, 5 * e, #16A34A)
sinon si b = 8 alors
// ECOLE : brique rouge, horloge et drapeau qui flotte
h vaut 16 * e
appelle dessinerCube(t, qx, qy, dxG * 0.75, dyG * 0.75, h, #FCA5A5, #DC2626, #B91C1C)
appelle dessinerToit(t, qx, qy, dxG * 0.75, dyG * 0.75, h, 9 * e, #57534E, #44403C)
appelle dessinerFenetres(t, qx, qy, dxG * 0.75, dyG * 0.75, h, 2, cFen)
cercle(t, qx, qy - h - 2 * e, 3 * e, #F8FAFC)
ligne(t, qx + dxG * 0.75, qy - h, qx + dxG * 0.75, qy - h - 20 * e, #E5E7EB, 2)
flot est un nombre
flot vaut (temps mod 4) * e
polygone(t, [qx + dxG * 0.75, qy - h - 20 * e, qx + dxG * 0.75 + 10 * e, qy - h - 18 * e + flot / 2, qx + dxG * 0.75, qy - h - 14 * e], #2563EB)
sinon si b = 9 alors
// CASERNE : grande porte de garage et gyrophare
h vaut 15 * e
appelle dessinerCube(t, qx, qy, dxG * 0.75, dyG * 0.75, h, #FECACA, #EF4444, #B91C1C)
polygone(t, [qx + 2 * e, qy - h + dyG * 0.75 + 4 * e, qx + dxG * 0.55, qy - h + dyG * 0.2 + 4 * e, qx + dxG * 0.55, qy - dyG * 0.2, qx + 2 * e, qy + dyG * 0.55], #F8FAFC)
rectangle(t, qx - 3 * e, qy - h - dyG * 0.75 - 4 * e, 6 * e, 4 * e, #44403C)
si temps mod 4 < 2 alors
cercle(t, qx, qy - h - dyG * 0.75 - 6 * e, 2.5 * e, #3B82F6)
appelle ajouterLumiere(qx, qy - h - dyG * 0.75 - 6 * e, 10 * e, rgba(59, 130, 246, 0.3))
sinon
cercle(t, qx, qy - h - dyG * 0.75 - 6 * e, 2.5 * e, #EF4444)
fin si
sinon si b = 11 alors
// BANQUE : colonnes, fronton et piece d'or
h vaut 17 * e
appelle dessinerCube(t, qx, qy, dxG * 0.75, dyG * 0.75, h, #F5F5F4, #E7E5E4, #D6D3D1)
kcol est un nombre
pour kcol de 0 à 2
uc est un nombre
uc vaut (kcol + 0.5) / 3
ligne(t, qx - dxG * 0.75 + uc * dxG * 0.75, qy - h + uc * dyG * 0.75 + 3 * e, qx - dxG * 0.75 + uc * dxG * 0.75, qy + uc * dyG * 0.75, #A8A29E, maximum(1, 2 * e))
ligne(t, qx + uc * dxG * 0.75, qy - h + dyG * 0.75 - uc * dyG * 0.75 + 3 * e, qx + uc * dxG * 0.75, qy + dyG * 0.75 - uc * dyG * 0.75, #A8A29E, maximum(1, 2 * e))
fin pour
appelle dessinerToit(t, qx, qy, dxG * 0.75, dyG * 0.75, h, 8 * e, #D6D3D1, #A8A29E)
saut est un nombre
saut vaut (temps mod 10) * 0.3 * e
cercle(t, qx, qy - h - 18 * e - saut, 6 * e, #FACC15)
cercle(t, qx, qy - h - 18 * e - saut, 4 * e, #EAB308)
si nuit alors
appelle ajouterLumiere(qx, qy - h - 18 * e, 12 * e, rgba(250, 204, 21, 0.25))
fin si
sinon si b = 12 alors
// PARC D'ATTRACTIONS : une grande roue qui tourne et un stand
appelle dessinerLosange(t, qx, qy, dxG * 0.85, dyG * 0.85, #FBCFE8, #F472B6)
appelle dessinerCube(t, qx + 10 * e, qy + 4 * e, dxG * 0.25, dyG * 0.25, 7 * e, #FDE68A, #F472B6, #DB2777)
rh est un nombre
rh vaut 15 * e
cyR est un nombre
cyR vaut qy - 24 * e
ligne(t, qx - 9 * e, qy, qx - 2 * e, cyR, #94A3B8, maximum(1, 2 * e))
ligne(t, qx + 5 * e, qy, qx - 2 * e, cyR, #94A3B8, maximum(1, 2 * e))
contour(t, #F472B6, maximum(1, 2 * e))
cercle(t, qx - 2 * e, cyR, rh, rgba(244, 114, 182, 0.08))
contour(t, #0)
krr est un nombre
pour krr de 0 à 5
angR est un nombre
angR vaut radians(temps * 6 + krr * 60)
ligne(t, qx - 2 * e, cyR, qx - 2 * e + cosinus(angR) * rh, cyR + sinus(angR) * rh, #FBCFE8, 1)
si krr mod 2 = 0 alors
cercle(t, qx - 2 * e + cosinus(angR) * rh, cyR + sinus(angR) * rh + 2 * e, 2.5 * e, #38BDF8)
sinon
cercle(t, qx - 2 * e + cosinus(angR) * rh, cyR + sinus(angR) * rh + 2 * e, 2.5 * e, #FACC15)
fin si
fin pour
cercle(t, qx - 2 * e, cyR, 2 * e, #F8FAFC)
h vaut 40 * e
si nuit alors
appelle ajouterLumiere(qx - 2 * e, cyR, 26 * e, rgba(244, 114, 182, 0.22))
fin si
sinon si b = 10 alors
// RUINES apres un incendie
polygone(t, [qx - 12 * e, qy, qx - 6 * e, qy - 8 * e, qx, qy - 3 * e, qx + 5 * e, qy - 10 * e, qx + 12 * e, qy], #57534E)
polygone(t, [qx - 8 * e, qy + 2 * e, qx - 3 * e, qy - 4 * e, qx + 3 * e, qy + 2 * e], #44403C)
cercle(t, qx + 2 * e, qy - 14 * e - (temps mod 12) * e, 4 * e, rgba(87, 83, 78, 0.4))
fin si
// incendie !
si feu[gy][gx] > 0 alors
appelle dessinerFlammes(t, qx, qy, h)
fin si
// pas d'electricite : un eclair rouge clignote
si courant = faux et b >= 2 et b <= 4 et temps mod 6 < 3 alors
cercle(t, qx, qy - h - 12 * e, 5 * e, #EF4444)
polygone(t, [qx + 1 * e, qy - h - 16 * e, qx - 2 * e, qy - h - 11 * e, qx + 1 * e, qy - h - 11 * e, qx - 1 * e, qy - h - 8 * e, qx + 3 * e, qy - h - 13 * e, qx, qy - h - 13 * e], #FDE68A)
fin si
fin procédure
// une route qui se raccorde a ses voisines, avec ses voitures
procédure dessinerRoute(t, qx, qy, gx, gy)
e est un nombre
e vaut ech
appelle dessinerSol(t, qx, qy - 2 * e, dxG, dyG, 3 * e, #3F3F46, #27272A, #18181B, #52525B)
haut est un nombre
haut vaut qy - 2 * e
nbVoisins est un nombre
nbVoisins vaut 0
// le milieu du bord de la case en direction de la premiere voisine
vx, vy est un nombre
vx vaut 0
vy vaut 0
kv est un nombre
pour kv de 0 à 3
nx est un nombre
ny est un nombre
nx vaut gx
ny vaut gy
si kv = 0 alors
nx vaut gx + 1
sinon si kv = 1 alors
nx vaut gx - 1
sinon si kv = 2 alors
ny vaut gy + 1
sinon
ny vaut gy - 1
fin si
si estRoute(nx, ny) alors
appelle versEcran(nx, ny)
demiX est un nombre
demiX vaut (ecX - qx) / 2
demiY est un nombre
demiY vaut (ecY - qy) / 2
// marquage au sol en pointilles vers la route voisine
ligne(t, qx + demiX * 0.15, haut + demiY * 0.15, qx + demiX * 0.45, haut + demiY * 0.45, #FDE68A, maximum(1, e))
ligne(t, qx + demiX * 0.7, haut + demiY * 0.7, qx + demiX * 0.95, haut + demiY * 0.95, #FDE68A, maximum(1, e))
si nbVoisins = 0 alors
vx vaut demiX
vy vaut demiY
fin si
nbVoisins ajoute 1
fin si
fin pour
si nbVoisins = 0 alors
rectangle(t, qx - 4 * e, haut - 1 * e, 8 * e, 2 * e, #FDE68A)
fin si
// lampadaire une case sur deux
si (gx + gy) mod 2 = 0 alors
ligne(t, qx - dxG * 0.6, haut, qx - dxG * 0.6, haut - 12 * e, #A1A1AA, 1)
si nuit alors
cercle(t, qx - dxG * 0.6, haut - 12 * e, 2 * e, #FEF08A)
appelle ajouterLumiere(qx - dxG * 0.6, haut - 10 * e, 18 * e, rgba(254, 240, 138, 0.18))
fin si
fin si
// une voiture passe (plus la ville est peuplee, plus il y en a)
si nbVoisins > 0 alors
densite est un nombre
densite vaut limiter(1 + pop / 120, 1, 5)
si (gx * 7 + gy * 13) mod 6 < densite alors
f est un nombre
f vaut ((temps * 3 + gx * 29 + gy * 47) mod 40) / 40
vox est un nombre
vox vaut qx - vx + 2 * vx * f
voy est un nombre
voy vaut haut - vy + 2 * vy * f
rectangle_arrondi(t, vox - 4 * e, voy - 4 * e, 8 * e, 5 * e, 2 * e, couleursV[(gx + gy * 3) mod 5])
rectangle(t, vox - 2 * e, voy - 5 * e, 4 * e, 2 * e, #1E293B)
si nuit alors
appelle ajouterLumiere(vox + vx * 0.2, voy + vy * 0.2, 8 * e, rgba(255, 255, 220, 0.3))
fin si
fin si
fin si
fin procédure
@ LA SIMULATION DU MOIS
// zone d'effet carree (comme dans le jeu d'origine), sans parcourir tout le plateau
procédure simulerMois()
ki est un nombre
kj est un nombre
r est un nombre
c est un nombre
b est un nombre
// --- 0. remise a zero ---
pour ki de 0 à COTE
pour kj de 0 à COTE
alim[ki][kj] vaut faux
pollu[ki][kj] vaut 0
eco[ki][kj] vaut faux
pomp[ki][kj] vaut faux
fin pour
fin pour
// --- 1. electricite, pollution, ecoles et pompiers ---
pour ki de 0 à COTE
pour kj de 0 à COTE
b vaut bat[ki][kj]
si b = 5 ou b = 4 ou b = 8 ou b = 9 alors
portee est un nombre
si b = 5 alors
portee vaut 6
sinon si b = 4 alors
portee vaut 3
sinon si b = 8 alors
portee vaut 5
sinon
portee vaut 6
fin si
pour r de maximum(0, ki - portee) à minimum(COTE, ki + portee)
pour c de maximum(0, kj - portee) à minimum(COTE, kj + portee)
dist est un nombre
dist vaut absolue(r - ki) + absolue(c - kj)
si b = 5 alors
alim[r][c] vaut vrai
si dist <= 4 alors
pollu[r][c] vaut pollu[r][c] + (5 - dist)
fin si
sinon si b = 4 alors
si dist <= portee alors
pollu[r][c] vaut pollu[r][c] + (portee - dist + 1)
fin si
sinon si b = 8 alors
si dist <= portee alors
eco[r][c] vaut vrai
fin si
sinon
si dist <= portee alors
pomp[r][c] vaut vrai
fin si
fin si
fin pour
fin pour
fin si
fin pour
fin pour
// les parcs et les bosquets nettoient l'air
pour ki de 0 à COTE
pour kj de 0 à COTE
si bat[ki][kj] = 6 ou bat[ki][kj] = 7 alors
rayonV est un nombre
rayonV vaut 1
force est un nombre
force vaut 1
si bat[ki][kj] = 6 alors
rayonV vaut 2
force vaut 2
fin si
pour r de maximum(0, ki - rayonV) à minimum(COTE, ki + rayonV)
pour c de maximum(0, kj - rayonV) à minimum(COTE, kj + rayonV)
pollu[r][c] vaut maximum(0, pollu[r][c] - force)
fin pour
fin pour
fin si
fin pour
fin pour
// --- 2. valeur du terrain des zones ---
pour ki de 0 à COTE
pour kj de 0 à COTE
si bat[ki][kj] = 2 ou bat[ki][kj] = 3 alors
v est un nombre
v vaut 50
bonusParc est un nombre
bonusParc vaut 0
usineProche est un booléen
usineProche vaut faux
pour r de maximum(0, ki - 3) à minimum(COTE, ki + 3)
pour c de maximum(0, kj - 3) à minimum(COTE, kj + 3)
dv est un nombre
dv vaut absolue(r - ki) + absolue(c - kj)
si bat[r][c] = 6 et dv <= 3 alors
bonusParc ajoute 8
fin si
si bat[r][c] = 4 et dv <= 2 alors
usineProche vaut vrai
fin si
fin pour
fin pour
v vaut v + minimum(24, bonusParc) - pollu[ki][kj] * 6
si eco[ki][kj] alors
v ajoute 10
fin si
si usineProche alors
v soustrait 12
fin si
val[ki][kj] vaut limiter(v, 0, 100)
fin si
fin pour
fin pour
// --- 3. comptage ---
pop vaut 0
emplois vaut 0
empCom est un nombre
empCom vaut 0
empInd est un nombre
empInd vaut 0
polTotal vaut 0
nbRes, nbCom, nbInd, nbRou, nbParc, nbCent, nbCoupe, nbEcole, nbCaserne, nbResEco, nbBanque, nbAttr est un nombre
nbBanque vaut 0
nbAttr vaut 0
nbRes vaut 0
nbCom vaut 0
nbInd vaut 0
nbRou vaut 0
nbParc vaut 0
nbCent vaut 0
nbCoupe vaut 0
nbEcole vaut 0
nbCaserne vaut 0
nbResEco vaut 0
pour ki de 0 à COTE
pour kj de 0 à COTE
b vaut bat[ki][kj]
si b = 1 alors
nbRou ajoute 1
sinon si b = 2 alors
nbRes ajoute 1
pop vaut pop + niv[ki][kj] * 14
polTotal vaut polTotal + pollu[ki][kj]
si eco[ki][kj] alors
nbResEco ajoute 1
fin si
sinon si b = 3 alors
nbCom ajoute 1
empCom vaut empCom + niv[ki][kj] * 10
sinon si b = 4 alors
nbInd ajoute 1
empInd vaut empInd + niv[ki][kj] * 18
sinon si b = 5 alors
nbCent ajoute 1
sinon si b = 6 alors
nbParc ajoute 1
sinon si b = 8 alors
nbEcole ajoute 1
sinon si b = 9 alors
nbCaserne ajoute 1
sinon si b = 11 alors
nbBanque ajoute 1
sinon si b = 12 alors
nbAttr ajoute 1
fin si
si b >= 2 et b <= 4 et alim[ki][kj] = faux alors
nbCoupe ajoute 1
fin si
fin pour
fin pour
emplois vaut empCom + empInd
// --- 4. la demande : de quoi la ville a-t-elle besoin ? ---
demR vaut emplois + 20 - pop
// des taxes trop fortes font fuir les entreprises
demC vaut arrondi(pop * 0.4) - empCom - (taxeCom - 9) * 3
demI vaut arrondi(pop * 0.6) - empInd + 15 - (taxeInd - 9) * 3
// --- 5. satisfaction ---
bonheur vaut 62 + nbParc * 4 + nbAttr * 3 - nbInd * 2 - (taxeHab - 9) * 4 - nbCoupe * 3 - polTotal
si emplois < pop alors
bonheur vaut bonheur - 10
fin si
si nbRes > 0 alors
bonheur vaut bonheur + arrondi(10 * nbResEco / nbRes)
fin si
bonheur vaut limiter(bonheur, 0, 100)
maxPena est un nombre
maxPena vaut 0
indicePop vaut "Population satisfaite"
si taxeHab > 9 et (taxeHab - 9) * 4 > maxPena alors
maxPena vaut (taxeHab - 9) * 4
indicePop vaut "La taxe d'habitation est trop lourde"
fin si
si emplois < pop et 10 > maxPena alors
maxPena vaut 10
indicePop vaut "Manque d'emplois : commerces, usines !"
fin si
si nbCoupe * 3 > maxPena alors
maxPena vaut nbCoupe * 3
indicePop vaut "Des foyers manquent d'électricité"
fin si
si polTotal > maxPena alors
maxPena vaut polTotal
indicePop vaut "Trop de pollution : ajoute des parcs"
fin si
si maxPena = 0 et pop >= 150 et nbEcole = 0 alors
indicePop vaut "Les familles réclament une école"
fin si
// --- 6. incendies ---
incendiesMois est un nombre
incendiesMois vaut 0
ruinesMois est un nombre
ruinesMois vaut 0
pour ki de 0 à COTE
pour kj de 0 à COTE
b vaut bat[ki][kj]
si b >= 2 et b <= 4 alors
si feu[ki][kj] > 0 alors
si pomp[ki][kj] alors
feu[ki][kj] vaut 0
message vaut "Les pompiers ont éteint un incendie !"
sinon
feu[ki][kj] vaut feu[ki][kj] - 1
si feu[ki][kj] = 0 alors
bat[ki][kj] vaut 10
niv[ki][kj] vaut 0
ruinesMois ajoute 1
sinon
// le feu peut se propager a une voisine
kv est un nombre
pour kv de 0 à 3
vi est un nombre
vj est un nombre
vi vaut ki
vj vaut kj
si kv = 0 alors
vi vaut ki - 1
sinon si kv = 1 alors
vi vaut ki + 1
sinon si kv = 2 alors
vj vaut kj - 1
sinon
vj vaut kj + 1
fin si
si vi >= 0 et vi <= COTE et vj >= 0 et vj <= COTE alors
si bat[vi][vj] >= 2 et bat[vi][vj] <= 4 alors
si feu[vi][vj] = 0 et non pomp[vi][vj] et hasard(1, 100) <= 25 alors
feu[vi][vj] vaut 3
fin si
fin si
fin si
fin pour
fin si
fin si
sinon si pop >= 100 et non pomp[ki][kj] et hasard(1, 1000) <= 12 alors
feu[ki][kj] vaut 3
incendiesMois ajoute 1
nbIncendies ajoute 1
fin si
fin si
fin pour
fin pour
// --- 7. croissance et declin des zones ---
pousses est un nombre
pousses vaut 0
declins est un nombre
declins vaut 0
pour ki de 0 à COTE
pour kj de 0 à COTE
b vaut bat[ki][kj]
si b >= 2 et b <= 4 alors
surRoute est un booléen
surRoute vaut estRoute(kj, ki - 1) ou estRoute(kj, ki + 1) ou estRoute(kj - 1, ki) ou estRoute(kj + 1, ki)
mauvais est un booléen
mauvais vaut surRoute = faux ou alim[ki][kj] = faux ou feu[ki][kj] > 0
si b = 2 et pollu[ki][kj] > 4 alors
mauvais vaut vrai
fin si
si mauvais alors
si niv[ki][kj] > 1 alors
niv[ki][kj] vaut niv[ki][kj] - 1
declins ajoute 1
fin si
sinon si niv[ki][kj] < 3 alors
peutPousser est un booléen
peutPousser vaut faux
si b = 2 alors
// le 3e niveau (immeuble) demande une ecole et un beau quartier
si demR > 0 et bonheur >= 45 et pollu[ki][kj] <= 2 alors
si niv[ki][kj] < 2 ou (eco[ki][kj] et val[ki][kj] >= 55) alors
peutPousser vaut vrai
fin si
fin si
sinon si b = 3 alors
si demC > 0 et bonheur >= 40 alors
si niv[ki][kj] < 2 ou val[ki][kj] >= 50 alors
peutPousser vaut vrai
fin si
fin si
sinon
si demI > 0 alors
peutPousser vaut vrai
fin si
fin si
si peutPousser et hasard(1, 100) <= 55 alors
niv[ki][kj] vaut niv[ki][kj] + 1
chantier[ki][kj] vaut 12
pousses ajoute 1
fin si
fin si
fin si
fin pour
fin pour
// --- 8. population finale, impots et charges ---
pop vaut 0
empCom vaut 0
empInd vaut 0
pour ki de 0 à COTE
pour kj de 0 à COTE
si bat[ki][kj] = 2 alors
pop vaut pop + niv[ki][kj] * 14
sinon si bat[ki][kj] = 3 alors
empCom vaut empCom + niv[ki][kj] * 10
sinon si bat[ki][kj] = 4 alors
empInd vaut empInd + niv[ki][kj] * 18
fin si
fin pour
fin pour
emplois vaut empCom + empInd
// --- LES TAXES : chacune a son propre taux ---
dImpHab vaut arrondi(pop * taxeHab / 100 * 6)
// --- LES AUTRES RECETTES ---
// les usines vendent leurs produits aux autres villes
dExport vaut arrondi(empInd * 0.6)
// les touristes viennent dans les parcs d'attractions (3 au maximum comptent)
// ils viennent plus nombreux si la ville est verte et heureuse
dTourisme vaut arrondi(minimum(nbAttr, 3) * (50 + nbParc * 5) * bonheur / 100)
// l'Etat aide les jeunes villes pendant leurs 2 premieres annees
dAide vaut 0
si (annee - 1) * 12 + mois <= 24 alors
dAide vaut AIDE_ETAT
fin si
dImpCom vaut arrondi(empCom * 3 * taxeCom / 100)
dImpInd vaut arrondi(empInd * 2 * taxeInd / 100)
// --- LA BANQUE : les habitants y placent leur argent ---
dIntBanque vaut 0
si nbBanque > 0 alors
// plus les habitants sont heureux, plus ils epargnent
depotsHab vaut depotsHab + arrondi(pop * 0.5 * bonheur / 100)
// la banque fait travailler cet argent et reverse des interets a la ville
dIntBanque vaut arrondi(depotsHab * TAUX_DEPOTS / 100)
fin si
// l'epargne de la ville rapporte des interets... qui restent places
dIntEpargne vaut arrondi(epargneVille * TAUX_EPARGNE / 100)
epargneVille vaut epargneVille + dIntEpargne
recettes est un nombre
recettes vaut dImpHab + dImpCom + dImpInd + dIntBanque + dExport + dTourisme + dAide
// l'entretien : une route coute peu, les commerces et usines s'entretiennent seuls
dEntretien vaut arrondi(nbRou / 4) + nbCent * 15 + nbParc * 2 + nbEcole * 10 + nbCaserne * 8 + nbBanque * 5 + nbAttr * 10
depenses est un nombre
depenses vaut dEntretien
argent vaut argent + recettes - depenses
// remboursement du credit bancaire
dCredit vaut 0
si pretMois > 0 alors
argent vaut argent - MENSUALITE
dCredit vaut MENSUALITE
depenses vaut depenses + MENSUALITE
pretMois soustrait 1
si pretMois = 0 alors
banniereTxt vaut "Crédit entièrement remboursé : bravo !"
banniereT vaut 40
fin si
fin si
// a decouvert, la banque fait payer des agios
dAgios vaut 0
si argent < 0 alors
dAgios vaut arrondi((0 - argent) * TAUX_AGIOS / 100)
argent vaut argent - dAgios
depenses vaut depenses + dAgios
fin si
si argent < 100 et pretMois = 0 alors
indicePop vaut "Caisses presque vides : vois les Finances [G]"
fin si
// courbe de la population
histPop ajoute pop
si longueur(histPop) > 36 alors
histPop supprime 0
fin si
si recettes - depenses >= 0 alors
gainTxt vaut "+" + convertir_texte(recettes - depenses) + " €"
gainPositif vaut vrai
sinon
gainTxt vaut convertir_texte(recettes - depenses) + " €"
gainPositif vaut faux
fin si
gainT vaut 25
mois vaut mois + 1
si mois > 12 alors
mois vaut 1
annee ajoute 1
fin si
message vaut "Fin du mois : +" + convertir_texte(recettes) + " € de recettes, -" + convertir_texte(depenses) + " € de dépenses (détails : touche G)"
si incendiesMois > 0 alors
message vaut "INCENDIE ! Construis une caserne de pompiers pres des maisons."
fin si
si ruinesMois > 0 alors
message vaut "Un bâtiment a brûlé... Rase les ruines avec [X]."
fin si
// --- 9. paliers ---
si palierIdx < 3 alors
si pop >= paliers[palierIdx] alors
argent vaut argent + palPrimes[palierIdx]
banniereTxt vaut "Ta ville devient un " + palNoms[palierIdx] + " ! Prime : +" + convertir_texte(palPrimes[palierIdx]) + " €"
banniereT vaut 40
palierIdx ajoute 1
fin si
fin si
si pop >= 600 alors
fini vaut vrai
reussite vaut vrai
sinon si argent <= -300 alors
fini vaut vrai
reussite vaut faux
fin si
fin procédure
@ LE DESSIN DE LA VILLE
procédure dessinerCiel(t)
// le jour passe pendant le mois : matin, midi, soir, nuit
si phaseJour < 0.55 alors
dégradé(t, [#7DD3FC, #BAE6FD, #E0F2FE])
sinon si phaseJour < 0.72 alors
dégradé(t, [#7C3AED, #F97316, #FDBA74])
sinon
dégradé(t, [#020617, #1E1B4B, #312E81])
ke est un nombre
pour ke de 0 à 24
cercle(t, (ke * 97) mod 640, 90 + (ke * 53) mod 160, 1 + ke mod 2, rgba(255, 255, 255, 0.6))
fin pour
cercle(t, 560, 120, 16, #FEF9C3)
cercle(t, 566, 115, 14, #1E1B4B)
fin si
si phaseJour < 0.55 alors
cercle(t, 80 + phaseJour * 900, 140 - sinus(radians(phaseJour * 300)) * 30, 18, #FDE047)
fin si
fin procédure
procédure dessinerTeinteVue(t, qx, qy, gx, gy)
coulT est un texte
coulT vaut ""
si modeVue = 1 alors
si alim[gy][gx] alors
coulT vaut rgba(250, 204, 21, 0.35)
sinon si bat[gy][gx] >= 2 et bat[gy][gx] <= 4 alors
coulT vaut rgba(239, 68, 68, 0.55)
fin si
sinon si modeVue = 2 alors
si pollu[gy][gx] > 0 alors
coulT vaut rgba(168, 85, 247, limiter(pollu[gy][gx] * 0.09, 0.1, 0.7))
fin si
sinon si modeVue = 3 alors
si bat[gy][gx] = 2 ou bat[gy][gx] = 3 alors
coulT vaut rgb(arrondi(60 + val[gy][gx] * 1.9), arrondi(80 + val[gy][gx] * 1.2), arrondi(200 - val[gy][gx] * 1.6))
fin si
sinon si modeVue = 4 alors
si eco[gy][gx] et pomp[gy][gx] alors
coulT vaut rgba(34, 197, 94, 0.45)
sinon si eco[gy][gx] alors
coulT vaut rgba(59, 130, 246, 0.4)
sinon si pomp[gy][gx] alors
coulT vaut rgba(239, 68, 68, 0.35)
fin si
fin si
si coulT <> "" alors
polygone(t, [qx, qy - dyG, qx + dxG, qy, qx, qy + dyG, qx - dxG, qy], coulT)
fin si
fin procédure
procédure dessinerVille(t)
effacer(t)
contour(t, #0)
ech vaut zoom / 100
dxG vaut 26 * ech
dyG vaut 13 * ech
phaseJour vaut compteurMois / dureeMois
nuit vaut phaseJour >= 0.72
vide lumX
vide lumY
vide lumR
vide lumC
appelle dessinerCiel(t)
profSol est un nombre
profSol vaut 12 * ech
// ordre du peintre : on dessine par diagonales, du fond vers l'avant
s est un nombre
pour s de -16 à 16
rX est un nombre
pour rX de maximum(-8, s - 8) à minimum(8, s + 8)
rY est un nombre
rY vaut s - rX
offX est un nombre
offY est un nombre
si orientation = 0 alors
offX vaut rX
offY vaut rY
sinon si orientation = 1 alors
offX vaut 0 - rY
offY vaut rX
sinon si orientation = 2 alors
offX vaut 0 - rX
offY vaut 0 - rY
sinon
offX vaut rY
offY vaut 0 - rX
fin si
gx est un nombre
gx vaut cX + offX
gy est un nombre
gy vaut cY + offY
si gx >= 0 et gx <= COTE et gy >= 0 et gy <= COTE alors
px est un nombre
px vaut 320 + (rX - rY) * dxG
py est un nombre
py vaut 270 + (rX + rY) * dyG
si px >= -80 et px <= 720 et py >= -80 et py <= 600 alors
si bat[gy][gx] = 1 alors
appelle dessinerSol(t, px, py, dxG, dyG, profSol, #3F8F52, #2F6E3E, #235430, #2B6B3C)
appelle dessinerRoute(t, px, py, gx, gy)
sinon
si (gx + gy) mod 2 = 0 alors
appelle dessinerSol(t, px, py, dxG, dyG, profSol, #3F8F52, #2F6E3E, #235430, #2B6B3C)
sinon
appelle dessinerSol(t, px, py, dxG, dyG, profSol, #45985A, #2F6E3E, #235430, #2B6B3C)
fin si
fin si
si modeVue > 0 alors
appelle dessinerTeinteVue(t, px, py, gx, gy)
fin si
// le curseur : vert si on peut construire ici, rouge sinon
si rX = 0 et rY = 0 alors
si peutConstruire() alors
appelle dessinerLosange(t, px, py, dxG, dyG, rgba(74, 222, 128, 0.35), #4ADE80)
sinon
appelle dessinerLosange(t, px, py, dxG, dyG, rgba(248, 113, 113, 0.30), #F87171)
fin si
fin si
si bat[gy][gx] > 1 alors
appelle dessinerBatiment(t, px, py, bat[gy][gx], niv[gy][gx], gx, gy)
si chantier[gy][gx] > 0 alors
chantier[gy][gx] vaut chantier[gy][gx] - 1
fin si
fin si
fin si
fin si
fin pour
fin pour
// la nuit tombe : on assombrit, puis on allume les lumieres
si phaseJour >= 0.62 alors
obscur est un nombre
obscur vaut limiter((phaseJour - 0.62) * 4, 0, 0.55)
rectangle(t, 0, 0, 640, 540, rgba(8, 12, 40, obscur))
fin si
si nuit et longueur(lumX) > 0 alors
kl est un nombre
pour kl de 0 à longueur(lumX) - 1
cercle(t, lumX[kl], lumY[kl], lumR[kl], lumC[kl])
fin pour
fin si
fin procédure
@ INTERFACE
procédure barreDemande(t, bx, lettreD, dem, coul)
label(t, bx, 72, lettreD, coul, 10)
rectangle(t, bx + 10, 64, 6, 12, rgba(255, 255, 255, 0.12))
hD est un nombre
hD vaut limiter(dem / 50, -1, 1) * 6
si hD > 0 alors
rectangle(t, bx + 10, 70 - hD, 6, hD, coul)
sinon si hD < 0 alors
rectangle(t, bx + 10, 70, 6, 0 - hD, #64748B)
fin si
fin procédure
procédure dessinerHud(t)
rectangle(t, 0, 0, 640, 82, rgba(15, 23, 42, 0.88))
// ligne 1 : titre, date, tresorerie, impot
label(t, 12, 22, "MA PETITE VILLE", #FFFFFF, 14)
si nuit alors
label(t, 150, 22, "Nuit", #A5B4FC, 11)
sinon
label(t, 150, 22, "Jour", #FDE68A, 11)
fin si
label(t, 190, 22, "Mois " + convertir_texte(mois) + " - An " + convertir_texte(annee), #94A3B8, 12)
rectangle(t, 190, 28, 100, 4, #334155)
progMois est un nombre
progMois vaut limiter(arrondi(100 * compteurMois / dureeMois), 0, 100)
si progMois > 0 alors
rectangle(t, 190, 28, progMois, 4, #38BDF8)
fin si
si argent < 0 alors
label(t, 316, 22, "Trésorerie : " + convertir_texte(argent) + " €", #F87171, 14)
sinon
label(t, 316, 22, "Trésorerie : " + convertir_texte(argent) + " €", #FDE68A, 14)
fin si
si gainT > 0 alors
si gainPositif alors
label(t, 340, 40 + gainT / 2, gainTxt, #4ADE80, 13)
sinon
label(t, 340, 40 + gainT / 2, gainTxt, #F87171, 13)
fin si
fin si
label(t, 520, 22, "Taxes " + convertir_texte(taxeHab) + "/" + convertir_texte(taxeCom) + "/" + convertir_texte(taxeInd) + " %", #CBD5E1, 11)
// ligne 2 : habitants, emplois, pollution, satisfaction
label(t, 12, 46, "Habitants : " + convertir_texte(pop), #86EFAC, 12)
label(t, 130, 46, "Emplois : " + convertir_texte(emplois), #7DD3FC, 12)
label(t, 240, 46, "Pollution : " + convertir_texte(polTotal), #C084FC, 12)
label(t, 380, 46, "Satisfaction", #CBD5E1, 11)
rectangle_arrondi(t, 462, 37, 120, 11, 5, #334155)
coulBo est un texte
si bonheur < 35 alors
coulBo vaut #EF4444
sinon si bonheur < 60 alors
coulBo vaut #FBBF24
sinon
coulBo vaut #22C55E
fin si
largBo est un nombre
largBo vaut limiter(arrondi(120 * bonheur / 100), 0, 120)
si largBo > 0 alors
rectangle_arrondi(t, 462, 37, largBo, 11, 5, coulBo)
fin si
label(t, 590, 47, convertir_texte(bonheur), coulBo, 12)
// ligne 3 : demande R C I, conseil, objectif
appelle barreDemande(t, 12, "R", demR, #4ADE80)
appelle barreDemande(t, 34, "C", demC, #38BDF8)
appelle barreDemande(t, 56, "I", demI, #FBBF24)
si indicePop = "Tout va bien" ou indicePop = "Population satisfaite" alors
label(t, 86, 72, indicePop, #86EFAC, 11)
sinon
label(t, 86, 72, indicePop, #FCA5A5, 11)
fin si
si palierIdx < 4 alors
label(t, 380, 72, "Objectif : " + palNoms[palierIdx] + " (" + convertir_texte(paliers[palierIdx]) + " hab.)", #FDE68A, 11)
rectangle(t, 380, 76, 200, 3, #334155)
si pop > 0 alors
rectangle(t, 380, 76, limiter(200 * pop / paliers[palierIdx], 0, 200), 3, #FDE68A)
fin si
fin si
// vue d'information active
si modeVue > 0 alors
rectangle_arrondi(t, 12, 90, label_largeur(nomsVues[modeVue], 12) + 20, 24, 10, rgba(15, 23, 42, 0.8))
label(t, 22, 106, nomsVues[modeVue], #FDE68A, 12)
fin si
// banniere de palier
si banniereT > 0 alors
largB est un nombre
largB vaut label_largeur(banniereTxt, 15) + 40
rectangle_arrondi(t, (640 - largB) / 2, 130, largB, 40, 14, rgba(250, 204, 21, 0.92))
label(t, (640 - largB) / 2 + 20, 156, banniereTxt, #422006, 15)
fin si
// message
rectangle(t, 0, 514, 640, 26, rgba(15, 23, 42, 0.88))
label(t, 10, 531, message, #F8FAFC, 12)
// ce qui est choisi pour construire (le menu complet : touche C)
rectangle_arrondi(t, 436, 470, 196, 38, 10, rgba(15, 23, 42, 0.88))
polygone(t, [456, 480, 468, 486, 456, 492, 444, 486], selCoul[sel - 1])
label(t, 476, 485, selNom[sel - 1], #F8FAFC, 12)
label(t, 476, 501, convertir_texte(selCout[sel - 1]) + " € [C] changer", #FDE68A, 10)
si pinceau alors
rectangle_arrondi(t, 500, 444, 132, 20, 8, rgba(250, 204, 21, 0.9))
label(t, 508, 458, "PINCEAU ACTIF (F)", #422006, 11)
fin si
si pretMois > 0 alors
rectangle_arrondi(t, 528, 88, 106, 32, 8, rgba(15, 23, 42, 0.85))
label(t, 536, 101, "Crédit : " + convertir_texte(MENSUALITE) + " €/mois", #FCA5A5, 10)
label(t, 536, 114, "encore " + convertir_texte(pretMois) + " mois", #CBD5E1, 10)
fin si
rectangle_arrondi(t, 8, 490, 300, 18, 8, rgba(15, 23, 42, 0.7))
label(t, 16, 503, "C construire G finances M menu B bâtir X raser", #CBD5E1, 10)
fin procédure
@ ECRAN de FIN
procédure dessinerFin(t)
effacer(t)
contour(t, #0)
si reussite alors
dégradé(t, [#052E16, #14532D, #052E16])
label(t, 110, 180, "MÉTROPOLE !", #FDE68A, 34)
label(t, 110, 230, convertir_texte(pop) + " habitants en " + convertir_texte(annee) + " année(s).", #F8FAFC, 16)
label(t, 110, 260, "Ta ville est devenue une vraie métropole.", #BBF7D0, 14)
sinon
dégradé(t, [#450A0A, #7F1D1D, #450A0A])
label(t, 110, 180, "FAILLITE", #FCA5A5, 34)
label(t, 110, 230, "Les caisses sont vides, la ville est saisie.", #F8FAFC, 16)
label(t, 110, 260, convertir_texte(pop) + " habitants partent après " + convertir_texte(annee) + " année(s).", #FECACA, 14)
fin si
label(t, 110, 290, "Incendies : " + convertir_texte(nbIncendies) + " Crédits pris : " + convertir_texte(nbPrets) + " Satisfaction : " + convertir_texte(bonheur), #CBD5E1, 13)
appelle dessinerGraphique(t, 110, 310, 420, 130)
label(t, 110, 480, "Appuie sur ESPACE pour revenir au menu", #93C5FD, 14)
fin procédure
// la courbe de la population mois apres mois
procédure dessinerGraphique(t, gx0, gy0, gl, gh)
rectangle_arrondi(t, gx0, gy0, gl, gh, 8, rgba(15, 23, 42, 0.75))
label(t, gx0 + 10, gy0 + 18, "Population, mois après mois", #94A3B8, 11)
nbH est un nombre
nbH vaut longueur(histPop)
si nbH < 2 alors
label(t, gx0 + 10, gy0 + gh / 2 + 10, "Pas encore assez de mois pour tracer la courbe", #64748B, 11)
sinon
maxH est un nombre
maxH vaut 50
kh est un nombre
pour kh de 0 à nbH - 1
maxH vaut maximum(maxH, histPop[kh])
fin pour
label(t, gx0 + gl - 60, gy0 + 18, "max " + convertir_texte(maxH), #86EFAC, 10)
bas est un nombre
bas vaut gy0 + gh - 12
hauteurG est un nombre
hauteurG vaut gh - 40
ligne(t, gx0 + 10, bas, gx0 + gl - 10, bas, #334155, 1)
pour kh de 1 à nbH - 1
xa est un nombre
xa vaut gx0 + 10 + (kh - 1) * (gl - 20) / (nbH - 1)
xb est un nombre
xb vaut gx0 + 10 + kh * (gl - 20) / (nbH - 1)
ya est un nombre
ya vaut bas - histPop[kh - 1] / maxH * hauteurG
yb est un nombre
yb vaut bas - histPop[kh] / maxH * hauteurG
ligne(t, xa, ya, xb, yb, #4ADE80, 2)
fin pour
cercle(t, gx0 + gl - 10, bas - histPop[nbH - 1] / maxH * hauteurG, 4, #4ADE80)
fin si
fin procédure
@ PROCESSUS TEMPS REEL : la simulation ET l'affichage
// Un seul processus est permis : il fait passer le temps, simule les mois
// et redessine la ville en continu. Le programme principal ne fait plus
// qu'ecouter le clavier.
processus Ville()
tant que enCours
tic ajoute 1
si ecranActif = 1 alors
si fini alors
ecranActif vaut 2
sinon
temps vaut temps + 1
compteurMois vaut compteurMois + 1
si compteurMois >= dureeMois alors
compteurMois vaut 0
appelle simulerMois()
fin si
si banniereT > 0 alors
banniereT soustrait 1
fin si
si gainT > 0 alors
gainT soustrait 1
fin si
fin si
appelle dessinerVille(graph)
appelle dessinerHud(graph)
sinon si ecranActif = 0 alors
appelle dessinerTitre(graph)
sinon si ecranActif = 2 alors
appelle dessinerFin(graph)
sinon si ecranActif = 3 alors
appelle dessinerAide(graph)
sinon si ecranActif = 5 alors
// pause : la ville est figee, le temps ne passe plus
appelle dessinerVille(graph)
appelle dessinerHud(graph)
appelle dessinerPause(graph)
sinon si ecranActif = 6 alors
appelle dessinerVille(graph)
appelle dessinerHud(graph)
appelle dessinerMenuConstruire(graph)
sinon si ecranActif = 7 alors
appelle dessinerVille(graph)
appelle dessinerHud(graph)
appelle dessinerMenuFinances(graph)
fin si
affiche graph
pause 100
fin tant que
fin processus
@ ACTIONS DU JOUEUR
procédure construire()
coutB est un nombre
coutB vaut selCout[sel - 1]
si bat[cY][cX] = 7 alors
message vaut "Défriche d'abord ce bosquet avec [X]"
sinon si bat[cY][cX] = 10 alors
message vaut "Rase d'abord ces ruines avec [X]"
sinon si bat[cY][cX] > 0 alors
message vaut "La case est déjà occupée"
sinon si pop < selDeb[sel - 1] alors
message vaut selNom[sel - 1] + " : débloqué à " + convertir_texte(selDeb[sel - 1]) + " habitants"
sinon si argent < coutB alors
message vaut "Il te manque " + convertir_texte(coutB - argent) + " € pour cela"
sinon
argent vaut argent - coutB
bat[cY][cX] vaut selBat[sel - 1]
si selBat[sel - 1] >= 2 et selBat[sel - 1] <= 4 alors
niv[cY][cX] vaut 1
sinon
niv[cY][cX] vaut 0
fin si
si selBat[sel - 1] >= 2 alors
chantier[cY][cX] vaut 15
fin si
message vaut selNom[sel - 1] + " construit pour " + convertir_texte(coutB) + " €"
fin si
fin procédure
procédure raser()
si bat[cY][cX] = 0 alors
message vaut "Il n'y a rien à raser ici"
sinon si bat[cY][cX] = 7 alors
si argent >= 5 alors
argent vaut argent - 5
bat[cY][cX] vaut 0
message vaut "Bosquet défriché (5 €)"
sinon
message vaut "Même 5 € sont de trop pour tes caisses"
fin si
sinon
si argent >= 8 alors
argent vaut argent - 8
bat[cY][cX] vaut 0
niv[cY][cX] vaut 0
feu[cY][cX] vaut 0
chantier[cY][cX] vaut 0
message vaut "Démolition effectuée (8 €)"
sinon
message vaut "Pas les moyens de démolir"
fin si
fin si
fin procédure
procédure nouvellePartie()
appelle genererTerrain()
argent vaut 1000
mois vaut 1
annee vaut 1
taxeHab vaut 9
pop vaut 0
emplois vaut 0
bonheur vaut 60
polTotal vaut 0
demR vaut 20
demC vaut 0
demI vaut 15
compteurMois vaut 0
palierIdx vaut 0
nbIncendies vaut 0
indicePop vaut "Tout va bien"
cX vaut 7
cY vaut 8
sel vaut 1
pinceau vaut faux
modeVue vaut 0
reussite vaut faux
pretMois vaut 0
nbPrets vaut 0
taxeCom vaut 9
taxeInd vaut 9
depotsHab vaut 0
epargneVille vaut 0
vide histPop
temps vaut 0
banniereT vaut 0
gainT vaut 0
message vaut "Une nouvelle ville t'attend. Le temps s'écoule !"
fini vaut faux
fin procédure
@ CREDIT BANCAIRE
procédure emprunter()
si pretMois > 0 alors
message vaut "Rembourse d'abord ton crédit en cours (" + convertir_texte(pretMois) + " mois restants)."
sinon
argent vaut argent + MONTANT_PRET
pretMois vaut DUREE_PRET
nbPrets ajoute 1
message vaut "La banque te prête " + convertir_texte(MONTANT_PRET) + " € : tu rembourseras " + convertir_texte(MENSUALITE) + " € par mois pendant " + convertir_texte(DUREE_PRET) + " mois."
banniereTxt vaut "+" + convertir_texte(MONTANT_PRET) + " € : crédit accordé !"
banniereT vaut 30
fin si
fin procédure
@ ECRAN TITRE
procédure dessinerTitre(t)
effacer(t)
contour(t, #0)
// le ciel passe lentement du jour a la nuit
phaseT est un nombre
phaseT vaut (tic mod 400) / 400
nuitT est un booléen
nuitT vaut phaseT > 0.55
si phaseT < 0.4 alors
dégradé(t, [#38BDF8, #7DD3FC, #E0F2FE])
cercle(t, 120 + phaseT * 800, 120, 26, #FDE047)
sinon si phaseT < 0.55 alors
dégradé(t, [#6D28D9, #F97316, #FDBA74])
sinon
dégradé(t, [#020617, #1E1B4B, #312E81])
ke est un nombre
pour ke de 0 à 30
si (ke + tic / 3) mod 7 > 0 alors
cercle(t, (ke * 97) mod 640, 20 + (ke * 53) mod 200, 1 + ke mod 2, rgba(255, 255, 255, 0.7))
fin si
fin pour
cercle(t, 540, 90, 20, #FEF9C3)
cercle(t, 548, 84, 18, #1E1B4B)
fin si
// les nuages
kn est un nombre
pour kn de 0 à 3
nxx est un nombre
nxx vaut (kn * 190 + tic * (1 + kn mod 2)) mod 760 - 60
ellipse(t, nxx, 60 + kn * 35, 40, 12, rgba(255, 255, 255, 0.35))
ellipse(t, nxx + 25, 54 + kn * 35, 28, 10, rgba(255, 255, 255, 0.3))
fin pour
// la ville au loin, qui defile doucement
kb est un nombre
bxx est un nombre
hb est un nombre
pour kb de 0 à 17
bxx vaut kb * 40 - (tic mod 40)
hb vaut skyH[kb mod 16] * 0.7
rectangle(t, bxx, 470 - hb, 36, hb, rgba(30, 41, 59, 0.6))
fin pour
// la ville au premier plan, avec ses fenetres
pour kb de 0 à 16
bxx vaut kb * 44 - ((tic * 2) mod 44)
hb vaut skyH[(kb + 5) mod 16]
rectangle(t, bxx, 540 - hb, 40, hb, #1E293B)
rectangle(t, bxx, 540 - hb, 40, 4, #334155)
kf est un nombre
pour kf de 0 à arrondi_inferieur(hb / 22) - 1
si nuitT et (kb * 7 + kf * 3) mod 4 > 0 alors
rectangle(t, bxx + 7, 550 - hb + kf * 22, 8, 8, #FEF08A)
rectangle(t, bxx + 24, 550 - hb + kf * 22, 8, 8, #FDE68A)
sinon
rectangle(t, bxx + 7, 550 - hb + kf * 22, 8, 8, #475569)
rectangle(t, bxx + 24, 550 - hb + kf * 22, 8, 8, #475569)
fin si
fin pour
fin pour
// le titre
label(t, 133, 103, "MA PETITE VILLE", rgba(0, 0, 0, 0.35), 44)
label(t, 130, 100, "MA PETITE VILLE", #FFFFFF, 44)
label(t, 172, 134, "Construis la ville de tes rêves !", #F8FAFC, 16)
// le menu
km est un nombre
pour km de 0 à 2
my0 est un nombre
my0 vaut 196 + km * 64
si km = menuSel alors
contour(t, #FDE68A, 3)
rectangle_arrondi(t, 200, my0, 240, 40, 20, rgba(250, 204, 21, 0.9))
contour(t, #0)
label(t, 320 - label_largeur(menuTitre[km], 17) / 2, my0 + 27, menuTitre[km], #422006, 17)
polygone(t, [178, my0 + 12, 192, my0 + 20, 178, my0 + 28], #FDE68A)
sinon
rectangle_arrondi(t, 200, my0, 240, 40, 20, rgba(15, 23, 42, 0.7))
label(t, 320 - label_largeur(menuTitre[km], 16) / 2, my0 + 26, menuTitre[km], #F8FAFC, 16)
fin si
fin pour
si msgMenu <> "" alors
label(t, 320 - label_largeur(msgMenu, 12) / 2, 438, msgMenu, #FCA5A5, 12)
fin si
rectangle_arrondi(t, 150, 500, 340, 26, 13, rgba(15, 23, 42, 0.75))
label(t, 168, 518, "Z / S : choisir ESPACE ou B : valider", #CBD5E1, 12)
fin procédure
@ COMMENT JOUER
procédure dessinerAide(t)
effacer(t)
contour(t, #0)
dégradé(t, [#0F172A, #1E293B, #0F172A])
label(t, 40, 50, "COMMENT JOUER", #FDE68A, 28)
label(t, 470, 48, "Page " + convertir_texte(pageAide + 1) + " / 2", #94A3B8, 13)
rectangle_arrondi(t, 30, 70, 580, 400, 14, rgba(255, 255, 255, 0.05))
si pageAide = 0 alors
label(t, 50, 100, "LES COMMANDES", #38BDF8, 15)
label(t, 50, 128, "Z Q S D déplacer le curseur", #F8FAFC, 13)
label(t, 50, 152, "C menu Construire (raccourcis : touches 1 à 9)", #F8FAFC, 13)
label(t, 50, 176, "B bâtir X raser (bosquets, ruines...)", #F8FAFC, 13)
label(t, 50, 200, "F pinceau : construire en se déplaçant", #F8FAFC, 13)
label(t, 50, 224, "V vues : électricité, pollution, terrain, services", #F8FAFC, 13)
label(t, 50, 248, "A / E / R tourner la caméra / zoomer / dézoomer", #F8FAFC, 13)
label(t, 50, 272, "T passer directement à la fin du mois", #F8FAFC, 13)
label(t, 50, 296, "G menu Finances : taxes, banque, crédit", #F8FAFC, 13)
label(t, 50, 320, "F pinceau V vues A/E/R caméra", #F8FAFC, 13)
label(t, 50, 344, "M menu pause (aide, retour au menu)", #F8FAFC, 13)
label(t, 50, 384, "LE BUT DU JEU", #38BDF8, 15)
label(t, 50, 410, "Atteindre 600 habitants pour devenir une MÉTROPOLE,", #F8FAFC, 13)
label(t, 50, 432, "sans tomber sous -300 € : sinon, c'est la faillite !", #F8FAFC, 13)
sinon
label(t, 50, 100, "FAIRE GRANDIR SA VILLE", #38BDF8, 15)
label(t, 50, 128, "- Une zone grandit seulement si elle touche une ROUTE", #F8FAFC, 13)
label(t, 50, 150, " et si une CENTRALE l'alimente en électricité.", #F8FAFC, 13)
label(t, 50, 176, "- Les barres R, C, I montrent ce qui manque : logements,", #F8FAFC, 13)
label(t, 50, 198, " commerces ou industries. Construis ce qui est demandé !", #F8FAFC, 13)
label(t, 50, 224, "- Les usines polluent : éloigne-les des maisons, ajoute des parcs.", #F8FAFC, 13)
label(t, 50, 250, "- Une ÉCOLE (dès 80 hab.) permet de bâtir des immeubles.", #F8FAFC, 13)
label(t, 50, 276, "- Une CASERNE (dès 120 hab.) éteint les incendies.", #F8FAFC, 13)
label(t, 50, 302, "- Près des parcs et des écoles, le terrain vaut plus cher.", #F8FAFC, 13)
label(t, 50, 336, "LA BANQUE (menu G)", #38BDF8, 15)
label(t, 50, 362, "Avec une BANQUE, les habitants épargnent : elle reverse 2 %/mois", #F8FAFC, 13)
label(t, 50, 384, "de leurs dépôts. Ta ville peut aussi placer son argent (+2 %/mois).", #F8FAFC, 13)
label(t, 50, 412, "L'argent : taxes, exportations des usines, touristes du parc", #86EFAC, 13)
label(t, 50, 432, "d'attractions (dès 60 hab.) et aide de l'État les 2 premières années.", #86EFAC, 13)
label(t, 50, 456, "Paliers : Village (100) - Bourg (250) - Ville (400) - Métropole (600)", #FDE68A, 12)
fin si
label(t, 120, 505, "Q / D : changer de page ESPACE : retour", #94A3B8, 13)
fin procédure
@ MENU CONSTRUIRE
procédure dessinerMenuConstruire(t)
rectangle(t, 0, 0, 640, 540, rgba(2, 6, 23, 0.55))
rectangle_arrondi(t, 50, 88, 540, 420, 16, rgba(15, 23, 42, 0.96))
rectangle_arrondi(t, 50, 88, 540, 5, 2, #4ADE80)
label(t, 72, 122, "CONSTRUIRE", #86EFAC, 22)
label(t, 380, 120, "Trésorerie : " + convertir_texte(argent) + " €", #FDE68A, 13)
label(t, 330, 142, "Coût", #64748B, 10)
label(t, 420, 142, "Entretien/mois", #64748B, 10)
kb est un nombre
pour kb de 0 à 9
yb est un nombre
yb vaut 148 + kb * 29
verrou est un booléen
verrou vaut pop < selDeb[kb]
si kb = constrSel alors
rectangle_arrondi(t, 64, yb, 512, 26, 10, rgba(74, 222, 128, 0.22))
polygone(t, [70, yb + 8, 78, yb + 14, 70, yb + 20], #86EFAC)
fin si
polygone(t, [100, yb + 6, 112, yb + 14, 100, yb + 22, 88, yb + 14], selCoul[kb])
label(t, 66 + 56, yb + 19, convertir_texte((kb + 1) mod 10), #64748B, 10)
si verrou alors
label(t, 140, yb + 19, selNom[kb], #64748B, 13)
label(t, 330, yb + 19, "dès " + convertir_texte(selDeb[kb]) + " habitants", #F87171, 11)
sinon
label(t, 140, yb + 19, selNom[kb], #F8FAFC, 13)
si argent >= selCout[kb] alors
label(t, 330, yb + 19, convertir_texte(selCout[kb]) + " €", #FDE68A, 12)
sinon
label(t, 330, yb + 19, convertir_texte(selCout[kb]) + " €", #F87171, 12)
fin si
label(t, 420, yb + 19, selEntr[kb], #CBD5E1, 12)
fin si
fin pour
rectangle_arrondi(t, 64, 444, 512, 30, 10, rgba(255, 255, 255, 0.05))
label(t, 76, 464, selDescr[constrSel], #BAE6FD, 12)
label(t, 72, 496, "Z / S : choisir ESPACE ou B : prendre C : fermer", #64748B, 11)
fin procédure
@ MENU FINANCES
procédure ligneFinance(t, k, yl, txt, valeurTxt, actif)
si k = finSel alors
rectangle_arrondi(t, 60, yl - 20, 280, 30, 10, rgba(250, 204, 21, 0.22))
polygone(t, [66, yl - 12, 74, yl - 6, 66, yl], #FDE68A)
fin si
si actif alors
label(t, 82, yl, txt, #F8FAFC, 13)
sinon
label(t, 82, yl, txt, #64748B, 13)
fin si
si valeurTxt <> "" alors
label(t, 330 - label_largeur(valeurTxt, 13), yl, valeurTxt, #FDE68A, 13)
fin si
fin procédure
procédure ligneBilan(t, yl, txt, montant, positif)
label(t, 372, yl, txt, #CBD5E1, 11)
si montant = 0 alors
label(t, 576 - label_largeur("0 €", 11), yl, "0 €", #64748B, 11)
sinon si positif alors
label(t, 576 - label_largeur("+" + convertir_texte(montant) + " €", 11), yl, "+" + convertir_texte(montant) + " €", #86EFAC, 11)
sinon
label(t, 576 - label_largeur("-" + convertir_texte(montant) + " €", 11), yl, "-" + convertir_texte(montant) + " €", #FCA5A5, 11)
fin si
fin procédure
procédure dessinerMenuFinances(t)
rectangle(t, 0, 0, 640, 540, rgba(2, 6, 23, 0.55))
rectangle_arrondi(t, 40, 88, 560, 420, 16, rgba(15, 23, 42, 0.96))
rectangle_arrondi(t, 40, 88, 560, 5, 2, #FACC15)
label(t, 60, 122, "FINANCES", #FDE68A, 22)
si argent < 0 alors
label(t, 200, 121, "Trésorerie : " + convertir_texte(argent) + " €", #F87171, 15)
sinon
label(t, 200, 121, "Trésorerie : " + convertir_texte(argent) + " €", #FDE68A, 15)
fin si
// colonne de gauche : ce que le maire peut regler
label(t, 60, 150, "LES TAXES", #38BDF8, 11)
appelle ligneFinance(t, 0, 174, "Taxe d'habitation", "< " + convertir_texte(taxeHab) + " % >", vrai)
appelle ligneFinance(t, 1, 206, "Taxe commerciale", "< " + convertir_texte(taxeCom) + " % >", vrai)
appelle ligneFinance(t, 2, 238, "Taxe industrielle", "< " + convertir_texte(taxeInd) + " % >", vrai)
label(t, 82, 256, "Plus de taxes = plus d'argent... mais moins de croissance !", #64748B, 9)
label(t, 60, 284, "LA BANQUE", #38BDF8, 11)
banqueOk est un booléen
banqueOk vaut faux
ki est un nombre
pour ki de 0 à COTE
kj est un nombre
pour kj de 0 à COTE
si bat[ki][kj] = 11 alors
banqueOk vaut vrai
fin si
fin pour
fin pour
appelle ligneFinance(t, 3, 308, "Placer 100 € (+" + convertir_texte(TAUX_EPARGNE) + " %/mois)", "", banqueOk)
appelle ligneFinance(t, 4, 340, "Retirer 100 €", "", banqueOk et epargneVille > 0)
appelle ligneFinance(t, 5, 372, "Emprunter " + convertir_texte(MONTANT_PRET) + " €", "", pretMois = 0)
label(t, 82, 390, "à rembourser : " + convertir_texte(MENSUALITE) + " €/mois pendant " + convertir_texte(DUREE_PRET) + " mois", #64748B, 9)
appelle ligneFinance(t, 6, 424, "Fermer", "", vrai)
si non banqueOk alors
label(t, 82, 448, "Construis une Banque pour épargner (dès 150 hab.)", #F87171, 11)
fin si
// colonne de droite : le bilan du dernier mois et la banque
rectangle_arrondi(t, 360, 140, 226, 234, 10, rgba(255, 255, 255, 0.04))
label(t, 372, 160, "BILAN DU DERNIER MOIS", #38BDF8, 11)
appelle ligneBilan(t, 178, "Taxe d'habitation", dImpHab, vrai)
appelle ligneBilan(t, 194, "Taxe commerciale", dImpCom, vrai)
appelle ligneBilan(t, 210, "Taxe industrielle", dImpInd, vrai)
appelle ligneBilan(t, 226, "Exportations des usines", dExport, vrai)
appelle ligneBilan(t, 242, "Tourisme", dTourisme, vrai)
appelle ligneBilan(t, 258, "Intérêts de la banque", dIntBanque, vrai)
appelle ligneBilan(t, 274, "Aide de l'État", dAide, vrai)
appelle ligneBilan(t, 290, "Entretien", dEntretien, faux)
appelle ligneBilan(t, 306, "Remboursement crédit", dCredit, faux)
appelle ligneBilan(t, 322, "Agios (découvert)", dAgios, faux)
ligne(t, 372, 331, 576, 331, #334155, 1)
resultat est un nombre
resultat vaut dImpHab + dImpCom + dImpInd + dExport + dTourisme + dIntBanque + dAide - dEntretien - dCredit - dAgios
appelle ligneBilan(t, 352, "RÉSULTAT", absolue(resultat), resultat >= 0)
rectangle_arrondi(t, 360, 380, 226, 98, 10, rgba(255, 255, 255, 0.04))
label(t, 372, 400, "Dépôts des habitants : " + convertir_texte(depotsHab) + " €", #86EFAC, 11)
label(t, 372, 418, "-> la banque verse " + convertir_texte(TAUX_DEPOTS) + " %/mois à la ville", #64748B, 10)
label(t, 372, 440, "Épargne de la ville : " + convertir_texte(epargneVille) + " €", #FDE68A, 11)
label(t, 372, 458, "(+" + convertir_texte(dIntEpargne) + " € d'intérêts le mois dernier)", #64748B, 10)
si pretMois > 0 alors
label(t, 372, 474, "Crédit en cours : encore " + convertir_texte(pretMois) + " mois", #FCA5A5, 10)
fin si
si msgFin <> "" alors
label(t, 60, 474, msgFin, #86EFAC, 12)
fin si
label(t, 60, 498, "Z / S : choisir Q / D : régler une taxe ESPACE : valider G : fermer", #64748B, 10)
fin procédure
// actions de la banque
procédure placerArgent()
si argent >= 100 alors
argent vaut argent - 100
epargneVille vaut epargneVille + 100
msgFin vaut "100 € placés à la banque."
sinon
msgFin vaut "Pas assez d'argent dans les caisses."
fin si
fin procédure
procédure retirerArgent()
montant est un nombre
montant vaut minimum(100, epargneVille)
si montant > 0 alors
epargneVille vaut epargneVille - montant
argent vaut argent + montant
msgFin vaut convertir_texte(montant) + " € retirés de la banque."
sinon
msgFin vaut "Ton épargne est vide."
fin si
fin procédure
fonction banqueConstruite()
ok est un booléen
ok vaut faux
ki est un nombre
pour ki de 0 à COTE
kj est un nombre
pour kj de 0 à COTE
si bat[ki][kj] = 11 alors
ok vaut vrai
fin si
fin pour
fin pour
retourne ok
fin fonction
@ MENU PAUSE
procédure dessinerPause(t)
rectangle(t, 0, 0, 640, 540, rgba(2, 6, 23, 0.6))
rectangle_arrondi(t, 70, 96, 500, 340, 16, rgba(15, 23, 42, 0.95))
rectangle_arrondi(t, 70, 96, 500, 5, 2, #FACC15)
label(t, 92, 132, "PAUSE", #FDE68A, 26)
label(t, 92, 156, "Mois " + convertir_texte(mois) + " - An " + convertir_texte(annee) + " " + convertir_texte(pop) + " habitants", #94A3B8, 12)
kp est un nombre
pour kp de 0 à 2
py0 est un nombre
py0 vaut 186 + kp * 52
si kp = pauseSel alors
rectangle_arrondi(t, 92, py0, 220, 36, 18, #FACC15)
label(t, 202 - label_largeur(menuPause[kp], 14) / 2, py0 + 24, menuPause[kp], #422006, 14)
sinon
rectangle_arrondi(t, 92, py0, 220, 36, 18, rgba(255, 255, 255, 0.07))
label(t, 202 - label_largeur(menuPause[kp], 14) / 2, py0 + 24, menuPause[kp], #F8FAFC, 14)
fin si
fin pour
appelle dessinerGraphique(t, 330, 176, 220, 130)
label(t, 340, 330, "Trésorerie : " + convertir_texte(argent) + " €", #FDE68A, 12)
label(t, 340, 350, "Satisfaction : " + convertir_texte(bonheur), #86EFAC, 12)
si pretMois > 0 alors
label(t, 340, 370, "Crédit : encore " + convertir_texte(pretMois) + " mois", #FCA5A5, 12)
fin si
si msgMenu <> "" alors
label(t, 92, 404, msgMenu, #86EFAC, 13)
fin si
label(t, 92, 424, "Z / S : choisir ESPACE : valider M : reprendre", #64748B, 11)
fin procédure
@ DEMARRAGE
Ville()
@ BOUCLE PRINCIPALE : le clavier, ecran par ecran
tant que enCours
si ecranActif = 0 alors
// ----- ECRAN TITRE -----
appuyer ["z", "s", " ", "b"] dans action
msgMenu vaut ""
si action = 1 alors
menuSel vaut (menuSel + 2) mod 3
sinon si action = 2 alors
menuSel vaut (menuSel + 1) mod 3
sinon si menuSel = 0 alors
appelle nouvellePartie()
ecranActif vaut 1
sinon si menuSel = 1 alors
pageAide vaut 0
ecranRetour vaut 0
ecranActif vaut 3
sinon
enCours vaut faux
fin si
sinon si ecranActif = 3 alors
// ----- AIDE -----
appuyer ["q", "d", " "] dans action
si action = 1 alors
pageAide vaut 0
sinon si action = 2 alors
pageAide vaut 1
sinon
ecranActif vaut ecranRetour
fin si
sinon si ecranActif = 2 alors
// ----- FIN DE PARTIE -----
appuyer [" "] dans action
ecranActif vaut 0
sinon si ecranActif = 6 alors
// ----- MENU CONSTRUIRE -----
appuyer ["z", "s", " ", "b", "c", "m"] dans action
si action = 1 alors
constrSel vaut (constrSel + 9) mod 10
sinon si action = 2 alors
constrSel vaut (constrSel + 1) mod 10
sinon si action = 3 ou action = 4 alors
sel vaut constrSel + 1
message vaut "Choix : " + selNom[sel - 1] + " (" + convertir_texte(selCout[sel - 1]) + " €) - B pour bâtir"
ecranActif vaut 1
sinon
ecranActif vaut 1
fin si
sinon si ecranActif = 7 alors
// ----- MENU FINANCES -----
appuyer ["z", "s", "q", "d", " ", "b", "g", "m"] dans action
si action = 1 alors
finSel vaut (finSel + 6) mod 7
msgFin vaut ""
sinon si action = 2 alors
finSel vaut (finSel + 1) mod 7
msgFin vaut ""
sinon si action = 3 ou action = 4 alors
// regler une taxe : Q baisse, D monte
pasTaxe est un nombre
pasTaxe vaut 1
si action = 3 alors
pasTaxe vaut -1
fin si
si finSel = 0 alors
taxeHab vaut limiter(taxeHab + pasTaxe, 0, 25)
sinon si finSel = 1 alors
taxeCom vaut limiter(taxeCom + pasTaxe, 0, 25)
sinon si finSel = 2 alors
taxeInd vaut limiter(taxeInd + pasTaxe, 0, 25)
fin si
sinon si action = 5 ou action = 6 alors
si finSel = 3 alors
si banqueConstruite() alors
appelle placerArgent()
sinon
msgFin vaut "Il faut d'abord construire une Banque."
fin si
sinon si finSel = 4 alors
si banqueConstruite() alors
appelle retirerArgent()
sinon
msgFin vaut "Il faut d'abord construire une Banque."
fin si
sinon si finSel = 5 alors
appelle emprunter()
msgFin vaut message
sinon si finSel = 6 alors
ecranActif vaut 1
fin si
sinon
ecranActif vaut 1
fin si
sinon si ecranActif = 5 alors
// ----- PAUSE -----
appuyer ["z", "s", " ", "m"] dans action
si action = 1 alors
pauseSel vaut (pauseSel + 2) mod 3
msgMenu vaut ""
sinon si action = 2 alors
pauseSel vaut (pauseSel + 1) mod 3
msgMenu vaut ""
sinon si action = 4 ou pauseSel = 0 alors
msgMenu vaut ""
ecranActif vaut 1
sinon si pauseSel = 1 alors
pageAide vaut 0
ecranRetour vaut 5
ecranActif vaut 3
sinon
msgMenu vaut ""
menuSel vaut 0
ecranActif vaut 0
fin si
sinon
// ----- LE JEU -----
appuyer ["z", "s", "q", "d", "b", "x", "c", "t", "a", "e", "r", "v", "f", "1", "2", "3", "4", "5", "6", "7", "8", "9", "m", "g", "0"] dans action
sX est un nombre
sY est un nombre
sX vaut 0
sY vaut 0
bouge est un booléen
bouge vaut faux
si ecranActif <> 1 alors
// la partie vient de se terminer : on ignore la touche
bouge vaut faux
sinon si action = 1 alors
sY vaut -1
bouge vaut vrai
sinon si action = 2 alors
sY vaut 1
bouge vaut vrai
sinon si action = 3 alors
sX vaut -1
bouge vaut vrai
sinon si action = 4 alors
sX vaut 1
bouge vaut vrai
sinon si action = 5 alors
appelle construire()
sinon si action = 6 alors
appelle raser()
sinon si action = 7 alors
// le menu Construire
constrSel vaut sel - 1
ecranActif vaut 6
sinon si action = 8 alors
compteurMois vaut dureeMois
sinon si action = 9 alors
orientation vaut (orientation + 1) mod 4
sinon si action = 10 alors
zoom vaut limiter(zoom + 20, 60, 180)
sinon si action = 11 alors
zoom vaut limiter(zoom - 20, 60, 180)
sinon si action = 12 alors
modeVue vaut (modeVue + 1) mod 5
message vaut nomsVues[modeVue]
sinon si action = 13 alors
pinceau vaut non pinceau
si pinceau alors
message vaut "Pinceau : chaque déplacement construit " + selNom[sel - 1]
appelle construire()
sinon
message vaut "Pinceau désactivé"
fin si
sinon si action >= 14 et action <= 22 alors
// raccourcis 1 a 9
sel vaut action - 13
message vaut "Choix : " + selNom[sel - 1]
sinon si action = 23 alors
pauseSel vaut 0
msgMenu vaut ""
ecranActif vaut 5
sinon si action = 24 alors
// le menu Finances
finSel vaut 0
msgFin vaut ""
ecranActif vaut 7
sinon si action = 25 alors
// touche 0 : le parc d'attractions
sel vaut 10
message vaut "Choix : " + selNom[sel - 1]
fin si
si bouge alors
mX est un nombre
mY est un nombre
si orientation = 0 alors
mX vaut sX
mY vaut sY
sinon si orientation = 1 alors
mX vaut 0 - sY
mY vaut sX
sinon si orientation = 2 alors
mX vaut 0 - sX
mY vaut 0 - sY
sinon
mX vaut sY
mY vaut 0 - sX
fin si
cX vaut limiter(cX + mX, 0, COTE)
cY vaut limiter(cY + mY, 0, COTE)
si pinceau et bat[cY][cX] = 0 alors
appelle construire()
fin si
fin si
fin si
fin tant que
@ AU REVOIR
pause 250
effacer(graph)
contour(graph, #0)
dégradé(graph, [#020617, #1E1B4B, #020617])
label(graph, 140, 250, "À bientôt, Monsieur le Maire !", #FDE68A, 26)
label(graph, 210, 290, "Ta ville t'attendra...", #CBD5E1, 15)
affiche graph